参考自:https://blog.csdn.net/sunSHINEEzy/article/details/78122485
- 构造函数之默认构造函数(调用的构造函数不用传递参数)
两种实例化方式都是默认构造函数
- 构造函数之初始化列表
红字部分即为初始化列表:一个引号,多个参数用逗号隔开,赋值用()
初始化列表特性:
- 其先于构造函数执行
- 其只能用于构造函数
- 其可以同时初始化多个数据成员
- 【注意】初始化列表的功用:对于类中的静态常量,不能用构造函数来初始化,必须使用初始化列表的方式
- 拷贝构造函数
拷贝构造函数的特点:
- 当用户没有定义构造函数时,编译器会自动生成一个默认的拷贝构造函数(构造函数也是如此)
- 当采用直接初始化或复制初始化实例化对象时,系统会自动调用拷贝构造函数
- 由于拷贝构造函数的特性,拷贝构造函数不能重载!!
- 【总结】构造函数总结:
- 【总结】所有参数带有默认值时,转变成了默认构造函数
【注意】初始化列表是所有构造函数都可以实现的.
- 析构函数(用于释放系统资源的函数)
定义格式:
析构函数特点:- 如果没有自定义的析构函数,则系统自动生成
- 析构函数在对象销毁时自动调用(与之相对应,构造函数在对象实例化时自动调用)
- 析构函数没有返回值(构造函数也是如此)、没有参数也不能重载
- 不允许在()内加任何的参数
- 【重要知识点】对象的生命历程
- 【总结】成员函数的分类
成员函数的参数修饰方式
对象实例化的方式
定义一个函数只要不是函数声明,就要记着写{},即使{}不写任何的语句。
总结:构造函数与析构函数的调用顺序
1、先执行 被组合对象的构造函数
(1)当类中有成员变量是其他类的对象时,首先调用成员变量的构造函数,调用顺序与声明顺序相同,之后调用自身类的构造函数。
(2)析构函数的调用顺序与对应的构造函数调用顺序相反。
2、被组合对象的构造顺序,预定义顺序有关系,与初始化列表的顺序没有关系
3、 特殊成员变量必须用参数列表初始化。const、&、对象。
4、static类型的成员变量,必须在类外初始化,且不带static关键字。
注意:构造函数中不要调用构造函数!!这是一种危险的行为!(匿名对象深究)
#include<iostream> #include<string> using namespace std; class Point { public: Point(int a,int b,int c) { this->a = a; this->b = b; this->c = c; cout << "这是Pointd的有3个默认参数的构造函数! "<<this->a<<" "<<this->b<<" "<<this->c<<endl; } Point(int a, int b) { this-> a= a; this->b = b; Point(3, 4, 5);//产生一个匿名对象,纸条语句执行结束,匿名对象会被析构。 cout << "这是Pointd的有2个默认参数的构造函数! " << this->a << " " << this->b << endl; } ~Point() { cout << "Point对象被析构了! "<<this->a << " " << this->b << " " << this->c << endl; } int getC() { return c; } private: int a; int b; int c; }; int run() { Point aa(1, 2); cout << aa.getC() << endl; //c的值为垃圾值,因为匿名对象被创建有立即析构了
//就算用不析构的方式,也是垃圾值,因为c是不同对象中的元素
//在2个参数的构造函数中,没有显式初始化c,不能通过构造其他对象而在本构造对象中访问未初始化的数据 return 0; } int main() { run(); cout << "hello world! "; return 0; }