1.类的6个默认成员函数
任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。
默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。
2.构造函数
2.1构造函数特性
构造函数的主要任务是初始化对象。
它有如下特征:
1. 函数名与类名相同。
2. 无返回值。
3. 对象实例化时编译器自动调用对应的构造函数。
4. 构造函数可以重载。
class Date { public: //1.无缺省 // (1)无参构造函数 Date() {} // 2.带参构造函数 Date(int year, int month, int day) { _year = year; _month = month; _day = day; } //eg: Date d1(); *1*函数重载的语法支持;*2*编译器会存在歧义,认为其是函数声明 /* //2.全缺省 如果是全缺省的构造函数, 只Date d1;都会存在歧义 Date() {} Date(int year = 2022, int month = 6, int day = 4) { _year = year; _month = month; _day = day; } */ private: int _year; int _month; int _day; }; void TestDate() { Date d1; // 调用无参构造函数 Date d2(2015, 1, 1); // 调用带参的构造函数 // 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明 // 以下代码的函数:声明了d3函数,该函数无参,返回一个日期类型的对象 // warning C4930: “Date d3(void)” Date d3();//错误 }
5. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。
6.编译器生成的默认构造函数的作用:
C++把类型分成内置类型(基本类型)和自定义类型。
内置类型/基本类型:语言本身定义的基础类型,包括 int / char / double 等等。
自定义类型:用 class / struct 等等定义的类型。
注意:
我们不写,编译器会默认生成的构造函数,内置类型不做处理,自定义类型会去调用它的默认构造函数。
有些编译器也会处理,但是那是个性化行为,并不是所有的编译器都会处理。
注意:C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即:内置类型成员变量在
类中声明时可以给默认值。class Time { public: Time() { cout << "Time()" << endl; _hour = 0; _minute = 0; _second = 0; } private: int _hour; int _minute; int _second; }; class Date { private: // 基本类型(内置类型) int _year = 1970; int _month = 1; int _day = 1; // 自定义类型 Time _t; }; int main() { Date d; //利用监视可查看 return 0; }
7. 无参的构造函数和全缺省的构造函数都称为默认构造函数,默认构造函数只能有一个。
注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为
是默认构造函数。所以,
(1)一般情况下,有内置类型成员,就需要自己写构造函数,不能用编译器自己生成的。
(2)全部都是自定义类型成员,可以考虑让编译器自己生成。
结论:
1.一般情况下,构造函数都需要我们自己写。
2.以下情况可用自动生成的默认构造:
a.内置类型成员都有缺省值,且初始化符合我们的要求。
b.全是自定义类型的构造,且这些类型都定义默认构造。
2.2代码仓库
gitee/jimmywang16/learn_1/class_object1112/构造函数
3.析构函数
3.1析构函数特性
1. 析构函数名是在类名前加上字符 ~。
2. 无参数无返回值类型。
3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载。
4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。5.编译器
生成的默认析构函数,对自定类型成员调用它的析构函数。6.如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类。
4.拷贝构造函数
4.1拷贝构造函数特征
1. 拷贝构造函数是构造函数的一个重载形式。
2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。
Date(const Date& d) { cout << "use Date(const Date& d)" << endl; _year = d._year; _month = d._month; _day = d._day; }
3. 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。
4. 编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了。
总结:
C++内置类型直接拷贝,自定义类型传参必须调用拷贝构造完成拷贝 。
5. 拷贝构造函数典型调用场景:
使用已存在对象创建新对象;
函数参数类型为类类型对象;
函数返回值类型为类类型对象;class Date { public: Date(int year = 1, int month = 1, int day = 1) { _year = year; _month = month; _day = day; } Date(const Date& d) { cout << "use Date(const Date& d)" << endl; _year = d._year; _month = d._month; _day = d._day; } private: int _year; int _month; int _day; }; int main() { Date d1(2024, 2, 26); Date d2(d1); return 0; }
5.赋值运算符重载
5.1.运算符重载
class Date
{
public:
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
bool operator<(const Date& x)
{
if (_year < x._year)
{
return false;
}
else if (_year == x._year && _month < x._month)
{
return false;
}
else if (_year == x._year && _month == x._month && _day < x._day)
{
return true;
}
return false;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
d1 < d2; //等价于下方
d1.operator<(d2);
return 0;
}
私有怎么办?——写到类的内部:
bool operator<(const Date& x)
{
if (_year < x._year)
{
return false;
}
else if (_year == x._year && _month < x._month)
{
return false;
}
else if (_year == x._year && _month == x._month && _day < x._day)
{
return true;
}
return false;
}
5.2赋值运算符重载
class Date
{
public :
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
Date (const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
Date& operator=(const Date& d)
{
if(this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
private:
int _year ;
int _month ;
int _day ;
};
******************重点区分******************
5.3前置++和后置++重载
5.4代码仓库
gitee/jimmywang16/learn_1/learn1113/赋值运算符重载及其相关
5.5 cout,cin
运算符重载是让自定义类型支持运算符;
两个运算符重载构成函数重载。
6.const成员
6.1用法
将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数
隐含的this指针(*this),表明在该成员函数中不能对类的任何成员进行修改(不能对this指向的内容进行修改,+、-、>、<、==、... 需加const)。
权限的放大
本质:const Date* const this
this本身不能被修改,this指向的内容也不能被修改。
注意:
const加在——不需要修改——对象成员变量的函数。
class Date
{
public:
//...
bool operator<(const Date& x) const;
bool operator==(const Date& x) const;
bool operator<=(const Date& x) const;
bool operator>(const Date& x) const;
bool operator>=(const Date& x) const;
bool operator!=(const Date& x) const;
static int Getmonthdays(int year, int month);
Date& operator+=(int days);
Date operator+(int days) const;
Date& operator++();
Date operator++(int);
Date& operator-=(int days);
Date operator-(int days) const;
Date& operator--();
Date operator--(int);
//...
int operator-(const Date& d) const;
void Print() const // const加在不需要修改——对象成员变量的函数
{
cout << _year << " / " << _month << " / " << _day << endl;
}
private:
//...
}
6.2易混淆
6.3代码仓库
learn1113/运算符重载、Date日期类和const成员
7.取地址及const取地址操作符重载
这两个默认成员函数一般不用重新定义 ,编译器默认会生成。
class Date { public : Date* operator&() { return this ; } const Date* operator&()const { return this ; } private : int _year ; // 年 int _month ; // 月 int _day ; // 日 };
这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需
要重载,比如想让别人获取到指定的内容!