C++ 默认构造函数与合成默认拷贝构造函数
默认构造函数
默认构造函数是可以不用实参进行调用的构造函数
默认构造函数调用时机
如果定义一个对象时没有提供初始化时,就使用默认构造函数。例如:
class A { public: A(bool _isTrue= true, int _num=10){ isTrue = isTrue; num = _num; }; //默认构造函数 bool isTrue; int num; }; int main() { A a; //调用类A的默认构造函数 }
什么情况会自动生成默认构造函数?
默认构造函数包括了以下两种情况:
1.没有带明显形参(隐含的this指针)的构造函数。
2.提供了默认实参的构造函数。
(1)合成默认构造函数总是不会初始化类的内置类型及复合类型的数据成员。(编译器不会为基本类型数据成员提供初始化,即这是不被编译器需要的;复合类型一般指数组、指针、结构体、枚举、共用体等等非对象成员)
(2)分清楚默认构造函数被程序需要与被编译器需要,只有被编译器需要的默认构造函数,编译器才会合成它。
1) 带有默认构造函数的类成员对象,如果一个类没有任何构造函数,但它含有一个成员对象,而后者有默认构造函数,那么编译器就为该类合成出一个默认构造函数。不过这个合成操作只有在构造函数真正被需要的时候才会发生;如果一个类A含有多个成员类对象的话,那么类A的每一个构造函数必须调用每一个成员对象的默认构造函数,而且必须按照类对象在类A中的声明顺序进行;
2) 带有默认构造函数的基类,如果一个没有任何构造函数的派生类派生自一个带有默认构造函数基类,那么该派生类会合成一个构造函数调用上一层基类的默认构造函数;
3) 带有一个虚函数的类
类带有虚函数可以分为两种情况:
a.类本身定义了自己的虚函数
b.类从继承体系中继承了虚函数(成员函数一旦被声明为虚函数,继承不会改变虚函数的”虚性质“)。
这两种情况都使一个类成为带有虚函数的类。这样的类也满足编译器需要合成默认构造函数的类,原因是含有虚函数的类对象都含有一个虚表指针vptr,编译器需要对vptr设置初值以满足虚函数机制的正确运行,编译器会把这个设置初值的操作放在默认构造函数中。如果设计者没有定义任何一个默认构造函数,则编译器会合成一个默认构造函数完成上述操作,否则,编译器将在每一个构造函数中插入代码来完成相同的事情。
4) 带有一个虚基类的类
虚基类的概念是存在于类与类之间的,是一种相对的概念。例如类A虚继承于类X,则对于A来说,类X是类A的虚基类,而不能说类X就是一个虚基类。虚基类是为了解决多重继承下确保子类对象中每个父类只含有一个副本的问题,比如菱形继承。合成一个默认构造函数为对象初始化虚基类指针。
5) 合成的默认构造函数中,只有基类子对象和成员类对象会被初始化。所有其他的非静态数据成员都不会被初始化。
合成默认拷贝构造函数
有三种情况会以一个对象的内容作为另一个对象的初值:
1) 对一个对象做显示的初始化操作,X xx = x;
2) 当对象被当做参数交给某个函数时;
3) 当函数传回一个类对象时;
1) 如果一个类没有拷贝构造函数,但是含有一个类类型的成员变量,该类型含有拷贝构造函数,此时编译器会为该类合成一个拷贝构造函数;
2) 如果一个类没有拷贝构造函数,但是该类继承自含有拷贝构造函数的基类,此时编译器会为该类合成一个拷贝构造函数;
3) 如果一个类没有拷贝构造函数,但是该类声明或继承了虚函数,此时编译器会为该类合成一个拷贝构造函数;
4) 如果一个类没有拷贝构造函数,但是该类含有虚基类,此时编译器会为该类合成一个拷贝构造函数;