1。默认构造函数
定义:默认构造函数就是在没有显示提供初始式时调用的构造函数。
其有两种形式:
1.不带参数的构造函数;
eg:example(){…………}
2.带参数,但所有的参数都提供默认实参的构造函数;
eg:example(int i=0, long j=6, char k='A'){…………}
如果用户的类中
没有显示的定义任何构造函数,编译器会在
编译需要的情况下为该类
生成一个不带参数的默认构造函数。(注意这三个严苛的要求)
这里有个疑问:如果某个类中定义了一个构造函数,那么再定义一个需要调用默认构造函数的类对象时就会发生编译错误。因为已经显示的定义了一个带参数的构造函数,所以在定义一个类对象时就需要按照已经定义的构造函数来定义类对象。
class B
{
public:
B(int i=0, int j=0, int k=8){}
int k;
};
class A
{
public:
A(int i){l=6;}
B b;
int l;
};
int main(void)
{
A a(5); //can compile sucessfullly.use "g++ -fdump-tree-original test3.cpp" command can find this constructor will call B's default constructor.
A a; //can not compile successfully.because there is no this kind constructot.
return 0
}
使用命令 g++ -fdump-tree-original test3.cpp 能够看到编译器究竟对C++的代码做了那些手脚,可以来验证一下各种情况。
分类一:C++编译器必须为未声明构造函数的class合成一个默认构造函数的4种情况
第一:本class A中某个成员变量是类对象B(该member object B需要有自己定义的default constructor,这样才能促使编译器为A生成default 构造函数,然后此构造函数中调用B的default constructor;),本class A需要合成一个default constructor调用此类对象的default constructor函数。
(经过验证,如果A,B都不定义default constructor,则编译器对A,B均不会生成default constructor;可能是没有必要,但是上述合成的default constructor可以被用来调用成员变量的default constructor)
(经过验证,如果A自己定义有default constructor,但是B没有定义自己的default constructor的话,使用上述命令产生的文件中是看不到编译为B合成的default constructor的。可能是没有合成的必要)
(经过验证,如果A,B均自己定义有default constructor的情况下,程序忘记了使A的default constructor调用B的default constructor函数,编译器是会帮忙加进去的)
(经过验证,如果A中定义一个default constructor函数,但并未指定调用B中的那个构造函数,如果B中只定义一个构造函数,编译是ok的,但是如果定义两个构造函数则不能编译通过,原因是A的构造函数不知道去调用B中的哪个构造函数)
第二:如果一个
没有任何constructor的class派生自一个带有default constructor的base class。那么它的default constructor会被合成出来。
第三:如果一个class声明了virtual function,如果该类
没有任何constructor,编译器也会为它合成default constructor。(如果声明有constructor,编译器会在他的constructor中添加些用来初始化_vptr的code)
第四:一个
没有声明任何constructor的class派生自一个继承串链,其中有一个或是多个virtual base classes,编译器也会合成出一个无参数的default constructor,在其中加入每个virtual base class的执行器存取操作的代码。(如果用户声明了constructors,编译器会在constructor中安插virtual base class执行期存取操作的的码)
上面四种分析合成出的default constructor都是nontrivial default constructors,不在此情况之内的都trivial default constructors,它们实际上并不会被
编译器合成出来。在合成的default constructors,只有base class subobjects和member class object会被初始化,所有其它的nonstatic data member,如整数、整数
指针、整数
数组等等都不会被编译器初始化。
另外,涉及到虚函数,虚基类的,之所以default constructor函数被合成出来,都是因为编译要往里加入给虚函数表指针赋值的语句。
分类二:C++编译器不会合成default constructor的情况
就是程序员自己声明了一个构造函数!(不要让编译器帮你,都自己做比较好)
其实总结最后一句话就是:所有的事情都自己做,不要让编译器来帮你,虚函数表指针的赋值除外。
参考:《深度探索C++对象模型》