【C++】日期类Date(详解)

🔥个人主页:Forcible Bug Maker

🔥专栏:C++

目录

前言

日期类

日期类实现地图

获取某年某月的天数:GetMonthDay

检查日期合法,构造函数,拷贝构造函数,赋值运算符重载及析构函数

日期类的+=day和+day

日期类的-=day和-day

前置++和后置++

前置--和后置--

比大小运算符的重载

日期-日期返回天数

暴力++法

直接相减法

const成员

流插入和流提取重载

友元(friend)

结语


前言

本篇主要内容:日期类的实现

上篇我们介绍了拷贝构造函数和赋值运算符重载两大类的默认成员函数,本篇将会介绍更多关于操作符重载的实例运用。日期类,是与日期相关的类,主要用于处理与日期和时间相关的操作。我们将在完善一个日期类的过程中加深对运算符重载的理解和运用。在理解操作符重载之后,最后两个默认成员函数学习起来也就不是什么大问题了。

日期类

日期类实现地图

在实现日期类之前,需事先要知道要实现哪些内容。我会给出一份类的指南,也就是成员变量和成员函数的声明,然后根据声明一步步实现其中的成员函数。在代码编写过程中,成员函数是可以直接定义在类内部的;但是在实际开发过程中,考虑到工程级项目的规模,一般采用声明和定义分离的方式经行类的实现。将声明统一放在 Date.h 中,把成员函数的定义统一放在 Date.cpp 中,道理跟C语言的声明定义分离一样。

#include<iostream>
#include<cassert>
using namespace std;class Date
{// 友元friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);
public:// 获取某年某月的天数int GetMonthDay(int year, int month);// 检查日期是否合法bool CheckDate();// 全缺省的构造函数Date(int year = 1900, int month = 1, int day = 1);// 拷贝构造函数// d2(d1)Date(const Date& d);// 赋值运算符重载// d2 = d3 -> d2.operator=(&d2, d3)Date& operator=(const Date& d);// 析构函数~Date();// 日期+=天数Date& operator+=(int day);// 日期+天数Date operator+(int day);// 日期-天数Date operator-(int day);// 日期-=天数Date& operator-=(int day);// 前置++Date& operator++();// 后置++Date operator++(int);// 后置--Date operator--(int);// 前置--Date& operator--();// >运算符重载bool operator>(const Date& d);// ==运算符重载bool operator==(const Date& d);// >=运算符重载bool operator >= (const Date& d);// <运算符重载bool operator < (const Date& d);// <=运算符重载bool operator <= (const Date& d);// !=运算符重载bool operator != (const Date& d);// 日期-日期 返回天数int operator-(const Date& d);void Print() {cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};// 输出流重载
ostream& operator<<(ostream& out, const Date& d);
// 输入流重载
istream& operator>>(istream& in, Date& d);

这份地图中大家也许会发现很多陌生的内容,如友元,重载前置++和后置++,流插入和流提取重载等。不过不用着急,接下来都会讲到。

获取某年某月的天数:GetMonthDay

GetMonthDay函数用于获取某年某月的天数,由于其在日期加天数和减天数运算符重载的函数中被频繁调用,且代码量较少,我们可以直接将其设置为内联,定义到类的内部定义到类内部的成员函数都默认加了内联inline,而分离定义的成员函数没有此特性)。

注:分离声明和定义的函数是无法内联的

int GetMonthDay(int year, int month)
{assert(month > 0 && month < 13);int months[13] = { -1,31,28,31,30,31,30,31,31,30,31,30,31 };if (month == 2 && (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)) {return 29;}else return months[month];
}

由于此函数定义在类的内部,故没有 Date:: 来指定命名空间,此函数的其他逻辑应该也好理解,最终通过传过来的年和月来确定当月的天数,考虑到闰年判断等问题。

检查日期合法,构造函数,拷贝构造函数,赋值运算符重载及析构函数

检查日期是否合法,需要检查月不能小于1或者大于12,日要根据年和月来判断,见代码:

bool Date::CheckDate() // 由于声明和定义分离,定义函数时需指定一下命名空间Date::
{if (_month < 1 || _month > 12|| _day < 1 || _day > GetMonthDay(_year, _month)) {return false;}else return true;
}

构造函数,拷贝构造以及赋值重载等没什么好说的,注意拷贝构造需判断一下日期是否合法:

// 全缺省的构造函数
Date::Date(int year, int month, int day)
{_year = year;_month = month;_day = day;if (!CheckDate()) {cout << "日期非法\n" << endl;}
}// 拷贝构造函数
// d2(d1)
Date::Date(const Date& d)
{_year = d._year;_month = d._month;_day = d._day;
}// 赋值运算符重载// d2 = d3 -> d2.operator=(&d2, d3)
Date& Date::operator=(const Date& d)
{_year = d._year;_month = d._month;_day = d._day;return *this;
}// 析构函数
Date::~Date()
{_year = 0;_month = 0;_day = 0;
}

日期类的+=day和+day

日期类可以+吗?答案是肯定的,不过不是两个日期相加,而是一个日期去+一个天数,如,今天是2024/4/20,加上5就是五天后,五天后是2024/4/25。如何实现+=,来看看代码:

// 日期+=天数
Date& Date::operator+=(int day)
{// 此处是对+的day为负时的处理if (day < 0) {*this -= (-day); // 复用了-=,下文会讲return *this;}_day += day;while (_day > GetMonthDay(_year, _month)) {_day -= GetMonthDay(_year, _month);++_month;if (_month == 13) {++_year;_month = 1;}}return *this;
}

如果day为大于0的数,首先将day的值加到成员变量_day上,然后循环判断_day是否大于当月天数,如果大于,就减去当月天数,_month+1,_year根据_month是否大于12判断自增;如果_day小于当月天数,则跳出循环。最后返回值是为了贴合内置类型连续运算赋值的规则,如,a=b+=c;而Date&引用返回则是为了减少拷贝

写道这里,就即将到类和对象一个神奇的使用方式了,它的名字叫——复用

我们可以直接复用+=来实现+,来看看具体的复用代码:

// 日期+天数
Date Date::operator+(int day)
{Date tmp(*this);tmp += day; // 复用+=return tmp;
}

日期+day的规则是不能改变运算日期的值,所以这里在成员函数中定义了一个tmp拷贝,用来执行运算操作,最后传值返回,是因为tmp作为临时变量,出了函数就会销毁。

注:这里提供的是+=复用+的设计模式。实际上,用+复用+=也是可行的,但是这种复用方式却比+=复用的质量差,大家感兴趣可以自行实现并考虑其中原因。

日期类的-=day和-day

-=day虽然思路和+=差不多,但是逻辑却比+=难搞一些,建议仔细思考后在上手写。

// 日期-=天数
Date& Date::operator-=(int day)
{// 当减的天数为负时的操作if (day < 0) {*this += (-day);// 复用了刚才写的+=return *this;}_day -= day;while (_day < 1) {--_month;if (_month == 0) {--_year;_month = 12;}day += GetMonthDay(_year, _month);}return *this;
}

在给_day+=天数时,注意加的是上个月的天数,并非本月天数。写了-=,-的实现也就是简单的复用操作了:

// 日期-天数
Date Date::operator-(int day)
{Date tmp(*this);tmp -= day;return tmp;
}

返回值是否引用返回和+=day和+day是同理的。

前置++和后置++

知道内置类型的前置++和后置++吗?如++a,a++等,它们的作用都是给变量a自增1,学了这么长时间,你是否对它们的区别了如指掌。本篇我们讲的是自定义类型的自增,如,日期类,我们要给一个自定义类型(日期类)自增,但计算机并不知道日期自增的规则,这时就需要人为提供内置类型的自增运算符。其实,上面刚刚讲过复用,我们直接复用+=和-=就可以了,你想想,什么是++?什么是--?不就是+=1和-=1嘛!

// 前置++:返回+1之后的结果
Date& Date::operator++()
{*this += 1;return *this;
}

注:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率

如果不提供参数,在C++的定义之下,默认就是放到对象前面的重载运算符:++d,但如果单将一个运算符放到对象后面构成运算符重载应该怎么办呢?看看C++提供的解决方式:

// 后置++:自增,返回自增之前的拷贝
Date Date::operator++(int)
{Date tmp(*this);*this += 1;return tmp;
}

前置++和后置++都是一元运算符,为了可以让前置++和后置++形成正确重载,C++规定后置++重载时多增加一个int类型的参数,但调用参数时该参数不用传递,编译器自动传递

注:后置++是先使用后+1,因此只需要返回+1前的值,故需要先将this保存一份,然后给this+1。而代码中的tmp是临时对象,因此只能以值得方式返回,而不能返回引用

前置--和后置--

不想多说了,四个字——同理,复用

// 前置--
Date& Date::operator--()
{*this -= 1;return *this;
}// 后置--
Date Date::operator--(int)
{Date tmp(*this);*this -= 1;return tmp;
}

注意区分前置和后置的区别,控制下返回值是否引用返回就行。

比大小运算符的重载

为什么要给日期提供比大小重载,因为内置类型无法完成比较日期的任务。比大小需要提供的重载函数就多了,包括 <,<=,==,>,>=,!= ,一套写下来,岂不是能把人累瘫,别着急,实际上,需要你完成的实际上只有两个,> 和 ==,当然你选择 < 和 ==,或者 <,!= 统统都可以,如果还没想通,没关系,来看看我是如何实现的,这里以> 和 ==为例。

// >运算符重载
bool Date::operator>(const Date& d)
{if (_year > d._year|| _year == d._year && _month > d._month|| _year == d._year && _month == d._month && _day > d._day) return true;return false;
}// ==运算符重载
bool Date::operator==(const Date& d)
{return _year == d._year&& _month == d._month&& _day == d._day;
}

这里是对于>和==的重载,其中逻辑不难理解。

此时如果我们想要实现 >= ,直接复用上面两个重载就可以了。

// >=运算符重载
bool Date::operator>=(const Date& d)
{return *this > d || *this == d;
}

发现C++运算符重载和复用的魅力了吗?

如果此时你需要一个 < 重载:

// <运算符重载
bool Date::operator<(const Date& d)
{return !(*this > d || *this == d);
}

如果此时你需要一个 <= 重载:

// <=运算符重载
bool Date::operator<=(const Date& d)
{return !(*this > d);
}

如果此时你需要一个  != 重载:

// !=运算符重载
bool Date::operator!=(const Date& d)
{return !(*this == d);
}

如果……哦,已经没有如果了,这就是所有的比大小运算符重载🙂,很有意思吧。

日期-日期返回天数

日期减日期为的是计算两个日期之间的天数间隔。对于日期相减,这里提供了两种实现方案。

暴力++法

找出日期中小的那个,然后通过记录每次++的次数n来记录两日期之间的间隔,同时设置一个变量flag来记录两个日期之间的差是正的还是负的。

// 日期-日期 返回天数
int Date::operator-(const Date& d)
{Date max = *this;// 假设大的那个是*thisDate min = d;int flag = 1;int n = 0;if (*this < d) { //判断并重置max和min以及日期间隔正负max = d;min = *this;flag = -1;}while (min != max) {++min;++n;}return n * flag;
}

此方法也是最好理解的一种,虽然暴力++会有一些消耗,但是对于目前计算机的算力来说却是微不足道的。

直接相减法

这个过程就稍稍有些复杂,你可以先确定max(大日期对象)下一年的第一天tmpmaxmin(小日期对象)本年的第一天tmpmin,让它们的差值✖365,加到 n 上,同时遍历一遍这些年,找到一个闰年就让n+1。最后定义两个整型变量(tmp1,tmp2),让tmpmin逐次++(++使用的是之前重载的日期类++,最好用前置++,减少拷贝的消耗),同时用tmp1计数,直到和min相等让max逐次++,同时tmp2计数,直到和tmpmax相等。这时让n减去tmp1和tmp2后,得到的就是两个日期之间的差值了。

以下是实现代码,亲测正确:

int Date::operator-(const Date& d)
{Date max = *this;Date min = d;int flag = 1;int n = 0;if (*this < d) {max = d;min = *this;flag = -1;}// 以上是比较日期确定max和minn += (max._year - min._year + 1) * 365;for (int i = min._year; i <= max._year; i++)if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)++n;// 以上是根据年计算间隔的天数Date tmpmax(max._year + 1, 1, 1);int tmp1 = 0;Date tmpmin(min._year, 1, 1);int tmp2 = 0;while (tmpmax != max) {++max;++tmp1;}while (tmpmin != min) {++tmpmin;++tmp2;}// 以上是日期矫正,计算tmp1和tmp2n -= tmp1;n -= tmp2;return n * flag;
}

对于日期相减,不止有这两种实现,大家想到一些别的方式也可以自己亲自试一试,还是很有意思的。

const成员

将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改

具体怎么修饰呢?写一个const在参数列表后面:

在()括号后放const是将隐式传递的*this指针类型变成了const *this指针类型,这种解决方案是为了应对*this无法被显示改变为const类型而产生的。

对于const类型的对象,和内置类型的const修饰规则非常相似,权限只能平移和缩小,而不能放大。看看代码案例:

const Date d1;
Date& d2 = d1;// 不支持,d2是Date类型,取d1的引用属权限放大
const Date& d3 = d1;//支持,权限平移Date d4;
const Date& d5 = d4;// 支持,权限缩小

对于const成员函数内部,是不可以调用非const成员函数的;而非const成员函数却可以调用其他的const成员函数

所以,对于一些不会改动Date对象数据的成员函数,尽量提供const类型的成员函数即可,如下:

// 获取某年某月的天数const版
int GetMonthDay(int year, int month)const
{assert(month > 0 && month < 13);int months[13] = { -1,31,28,31,30,31,30,31,31,30,31,30,31 };if (month == 2 && (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)) {return 29;}else return months[month];
}

GetMonthDay定义在类内部,故不需要限定命名空间。

// 检查日期是否合法const版
bool Date::CheckDate()const
{if (_month < 1 || _month>12|| _day < 1 || _day>GetMonthDay(_year, _month)) {return false;}else return true;
}

基本上就是在函数()后加上const即可,需要这样调整的函数还包括比大小重载函数,日期相减函数,-day和+day,Print打印日期函数等等,这里就不一一列举了。

流插入和流提取重载

大家之前可能接触过C语言,这里就能体现出C语言输入输出的局限性了,它没办法支持对象类型的输入输出。在C++标准库<iostream>(包含istream类和ostream类)中,内含了输入流对象cin和输出流对象cout,通过使用这两个对象,我们可以支持输出所有的内置类型变量。今天要讲的流插入和流提取重载,就是可以帮助大家直接用cin和cout支持内置类型的输入输出。

如果需要定义一个流插入的重载,你会如何定义呢?

void Date::operator<<(ostream& out)
{cout << _year << "-" << _month << "-" <<_day <<endl;
}

是这样吗?那就大错特错了,按照运算符重载规则,

cout << d;

这种书写方式明显不符合重载时的参数顺序,所以如果想要调用上面这份重载,需要这样写:

d << cout;

但是,这种使用方式明显违背了像内置类型那样使用输入输出流的初衷。产生这种问题的主要原因还是无法改变调用类内部定义的成员函数时第一个传过去的元素永远是this指针

为解决这样的问题,需要我们把流插入和流提取的函数重载在类的外部,像下面这样:

ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "年" << d._month << "月" << d._day << "日" << endl;return out;
}

这里返回一个对象引用类型是为了贴合内置类型的使用规则,连续输出,如cout << a << b << c;如果没有此返回值,那么使用对象时,就只能用一次cout打印一个Date对象,如cout << d;而不是cout << d1 << d2 << d3;。

流提取也是同样的方法:

istream& operator>>(istream& in, Date& d)
{cout << "请输入年月日,用空格分隔:";in >> d._year >> d._month >> d._day;if (!d.CheckDate()) {cout << "日期非法\n" << endl;}return in;
}

返回一个对象的引用也是为了贴合内置类型使用规则。

到这里,你不免会问,如果将重载函数定义在了类的外部,那么该如何使用类内部定义的私有成员变量,如_year,_month,_day呢?别急,接下来补一下之前挖的坑,友元。

友元(friend)

在C++中,友元(Friend)是一个特殊的机制,它允许一个非成员函数或者一个类(或类的成员函数)访问另一个类的私有(private)或保护(protected)成员。友元不是类的成员,但它可以访问类的所有成员,包括私有和保护成员。这种访问权限的赋予是通过在类的定义中使用friend关键字来实现的。只需要在类的内部添加上类外定义的函数的声明,并在声明前加上关键字friend即可,一般这种友元函数允许写在类内部的任意地方,一般来说会把它放在整个类的开头。当一个函数成为一个类的友元,那么这个函数内部就可以随意使用类中的私有(private)或保护(protected)成员了

class Date
{// 友元friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);
public://。。。
private://。。。
}

结语

本篇博客实现了日期类Date,加深对运算符重载的运用,讲了前置++和后置++:传一个改变成后置++样式的int;还讲到const成员:由于无法改变*this类型而添加的const;流插入和流提取重载:由于无法改变传参顺序而定义到类的外部等等。这篇博客也算是对之前学到类和对象内容的一个阶段性的应用和总结吧。

博主后续还会产出更多有意思的内容,感谢大家的支持!♥

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/826580.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构2-线性表】

数据结构2-线性表 1 线性表-数组2 线性表-单链式结构2.1 前插顺序单链表2.2 后插顺序单链表2.3 循环单链表2.4 双向链表 总结 线性表、栈、队列、串和数组都属于线性结构。 线性结构的基本特点是除第一个元素无直接前驱&#xff0c;最后一个元素无直接后继之外&#xff0c;其他…

.net反射(Reflection)

文章目录 一.概念&#xff1a;二.反射的作用&#xff1a;三.代码案例&#xff1a;四.运行结果&#xff1a; 一.概念&#xff1a; .NET 反射&#xff08;Reflection&#xff09;是指在运行时动态地检查、访问和修改程序集中的类型、成员和对象的能力。通过反射&#xff0c;你可…

【游戏专区】飞机大战

打过飞机的人都知道&#xff0c;不是那么好打滴&#xff0c;求得麻袋&#xff0c;甩掉你那脑子里的黄色信息。活不多说&#xff0c;我们开始吧。 1、easyX的原理 基于Windows图形编程&#xff0c;将Windows下的复杂程序过程进行封装&#xff0c;仅给用户提供一个简单熟悉的接…

21.组件组成

组件组成 组件最大的优势就是可复用性 当使用构建步骤时&#xff0c;我们一般会将 Vue 组件定义在一个单独的 .vue 文件中&#xff0c;这被叫做单文件组件(简称 SFC) 组件组成结构 <template><div>承载标签</div> </template> <script> expor…

【软件测试】正交表测试例题

【软件测试】正交表测试 例题1答案 例题2答案 例题3答案 例题1 很多Word编辑器都有字体修饰功能&#xff0c;可以将一个字加粗、倾斜、以及加上下划线。一个字可以同时被加粗和倾斜&#xff0c;也可以同时被倾斜和加下划线。三种因子Bold, Italic, Underline的效果可以任意组合…

计算机组成原理【CO】Ch3 存储系统

文章目录 考纲3.1 存储系统概述3.2 主存储器3.3 主存储器与CPU的连接3.4 外部存储器3.5 高速缓冲存储器3.6 虚拟存储器 【※】存储系统总体流程图【※】各个部件的存储位置计算机存储相关硬件与数据结构说明进程控制块&#xff08;PCB&#xff09;页表页表始址页表始址寄存器&a…

传感器融合 | 适用于自动驾驶场景的激光雷达传感器融合项目_将激光雷达的高分辨率成像+测量物体速度的能力相结合

项目应用场景 面向自动驾驶场景的激光雷达传感器融合&#xff0c;将激光雷达的高分辨率成像测量物体速度的能力相结合&#xff0c;项目是一个从多个传感器获取数据并将其组合起来的过程&#xff0c;可以更加好地进行环境感知。项目支持 ubuntu、mac 和 windows 平台。 项目效果…

CGLIB动态代理

文章目录 前言概要SpringBoot中使用小结 前言 当我们需要在Java中实现动态代理时&#xff0c;通常会考虑使用 JDK原生动态代理 或者 CGLIB动态代理。 我这里说一下CGLIB动态代理&#xff0c;并给出一个例子。 概要 CGLIB&#xff08;Code Generation Library&#xff09;是一…

ROS分布式通讯配置

4WD 必读&#xff1a;分布式通讯是相对于用虚拟机来连接小车上主机来说&#xff0c;如果是 4WD 笔记本无主 机用户&#xff0c;不存在分布式通讯一说。 1.4WD 用户单笔记设置一&#xff0c;连接底盘和雷达还有摄像头。 因为虚拟机带宽问题&#xff0c;无法保证摄像头正常运行。…

初始ansible变量及实例配置

目录 1、为什么要使用变量 2、变量分类 3、 变量详解 3.1 vars,vars_files , group_vars 3.1 .1 vars 剧本中定义变量 3.1.2 vars_file 将变量存放到一个文件中&#xff0c;并在剧本中引用 3.1.3 group_vars 创建一个变量文件给某个组使用 实例1-根据不同的主机…

云手机助力舆情监测,智慧引领信息时代

随着信息时代的到来&#xff0c;舆情监测已成为政府、企业、高校、金融机构等各行业的必备利器。在这个信息爆炸的时代&#xff0c;如何及时准确地感知民意、把握市场动态&#xff0c;已成为各界迫切需要解决的问题。而云手机作为信息时代的新生力量&#xff0c;在舆情监测方面…

Python 数据结构和算法实用指南(四)

原文&#xff1a;zh.annas-archive.org/md5/66ae3d5970b9b38c5ad770b42fec806d 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第十二章&#xff1a;字符串算法和技术 根据所解决的问题&#xff0c;有许多流行的字符串处理算法。然而&#xff0c;最重要、最流行和最有…

代码随想录阅读笔记-回溯【重新安排行程】

题目 给定一个机票的字符串二维数组 [from, to]&#xff0c;子数组中的两个成员分别表示飞机出发和降落的机场地点&#xff0c;对该行程进行重新规划排序。所有这些机票都属于一个从 JFK&#xff08;肯尼迪国际机场&#xff09;出发的先生&#xff0c;所以该行程必须从 JFK 开…

【1569】jsp学生学籍管理系统Myeclipse开发sqlserver数据库web结构jsp编程计算机网页项目

一、源码特点 jsp 学生学籍管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为sqlserver2…

MYSQL之增删改查(中)

前言&#xff1a; 以下是MySQL最基本的增删改查语句&#xff0c;很多IT工作者都必须要会的命令&#xff0c;也 是IT行业面试最常考的知识点&#xff0c;由于是入门级基础命令&#xff0c;所有所有操作都建立在单表 上&#xff0c;未涉及多表操作。 4、“查”——之单表查询 My…

Gamba:将高斯溅射与Mamba结合用于单视图3D重建

Gamba: Marry Gaussian Splatting with Mamba for Single-View 3D Reconstruction Gamba&#xff1a;将高斯溅射与Mamba结合用于单视图3D重建 Qiuhong Shen11  Xuanyu Yi31 Zike Wu31  Pan Zhou2,42 Hanwang Zhang3,5 沈秋红 1 易轩宇 3 吴子可 3 潘周 2,4 2 张汉旺 3,5Shu…

C语言开源库iniparser解析ini文件

1 ini文件介绍 INI&#xff08;Initialization File&#xff09;文件是一种简单直观的数据存储格式&#xff0c;常用于配置应用程序的初始化设置。这种文件通常包含若干个节&#xff08;section&#xff09;和键值对&#xff08;key-value pairs&#xff09;。INI文件的每一部…

Spring AOP(面向切面编程)

1.Spring AOP 简介 1.1 AOP概述 AOP 为 Aspect Oriented Programming 的缩写&#xff0c;意思为面向切面编程, 是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP 是 OOP 的延续&#xff0c;是Spring框架中的一个重要内容&#xff0c;是函数式编程的一…

FPGA Quartus IP核 打开使用

两种Quartus版本下的IP核&#xff0c;从使用者的角度来看仅仅是配置界面不同&#xff0c;在参数设置和使用方法上基本一致。本文以“MegaWizard Plug-In Manager”中的FIR Compiler IP核使用为例。 Quartus的FIR IP核属于收费IP&#xff0c;如果是个人学习使用需要对IP核单独破…

C++ 深入理解 继承

本篇文章将谈谈一下几个问题&#xff1a; 1.基类和派生类对象赋值转换 2.继承中的作用域 3.派生类的默认成员函数 4.复杂的菱形继承及菱形虚拟继承 5.其他 1.基类和派生类对象赋值转换 1.派生类对象 可以赋值给 基类的对象 / 基类的指针 / 基类的引用。这里有个形象的说法叫切…