那么,什么时候才会合成出一个default constructor呢?——当编译器需要它的时候!此外,被合成出来的constructor只执行编译器所需的行动。
[x] “任何class如果没有定义default constructors,就会被合成出一个来”?——错
[x] “编译器合成出来的default constructors会显式设定class内每一个data member默认值”?——错
原文地址:https://www.qingdujun.com/zh-CN/cpp-default-constructors.html
以下分别讨论了编译器会主动合成出default constructor的四种情况。
文章目录
1.“带有Default Constructor”的Member Class Object
举个例子:Bar类没有任何构造函数
,但它内含一个成员对象
,而Foo类有默认构造函数
,此时编译器需要为Bar类合成出一个构造函数。(大概这个样子…)
class Foo {//explict constructor
public:
Foo(){}
};
class Bar {//no default constructor
public:
Foo foo; //member object
char* str;
};
编译器为什么要为Bar
类合成构造函数?(答:因为要构造Foo
类)。
Bar类“无”构造函数时
那么,编译器合成的构造函数大概是什么样子呢?(答:伪代码如下)。
Bar::Bar(){
foo.Foo::Foo();
}
Bar类“有”构造函数时
如果,有构造函数,那么编译器就会扩张(改写)已有的构造函数。编译器附加上的代码会在用户自定义的代码之前(大概是这个样子…)explicit user code
表示是用户自定义的代码部分。
Bar::Bar(){
foo.Foo::Foo(); //compiler code
//...explicit user code
}
另外,还有点需要注意的:“如果Bar类中有多个
类似于Foo类这样的成员对象
,那么编译器扩张(或者生成)构造函数的时候,会按照成员对象的声明顺序,生成foo.Foo::Foo()
类似的代码”。
2.“带有Default Constructor”的Base Class
举个例子:基类Foo含有默认的构造函数
,而子类Bar却没有声明构造函数,此时编译器会为Bar类合成一个构造函数。为什么会被合成?(答:因为要调用基类的构造函数,并初始化基类)
class Foo {//explict constructor
public:
Foo(){}
};
class Bar : public Foo {
public:
char* str;
};
注意:一直说的是带有默认构造函数
(就是显示声明了一个不需要任何参数的构造函数,或者全部有默认参数的构造函数),这点儿要注意。否则的话必须显示指定构造函数,而不能由编译器合成。
3.“带有一个Virtual Function”的Class
举个例子:(如下)class声明(或继承)一个virtual function。这种情况下,编译器为什么要合成构造函数?答案…在见下文。
class Foo {
public:
virtual void foo() = 0;
};
class Bar : public Foo {
public:
char* str;
};
答:因为编译器需要…一些信息,所以需要合成构造函数。那么,需要什么呢?
其一,编译器会构造一个virtual function table,里面存放类的virtual function地址。
其二,编译器会在每一个类中增加一个vptr指针(它用来指向上面的虚函数表…)。
4.“带有Virtual Base Class”的Class
举个例子:(如下)必须使得虚基类在子类中的位置,能够在执行期间确定。那么,编译器需要做什么?这个等以后再补充。。。
class Foo {
};
class Foo1 : virtual public Foo {
//__vbcFoo
};
class Foo2 : virtual public Foo {
};
class Bar : public Foo1, public Foo2 {
};
2018-12-10 北京 海淀
Reference: 《深度探索C++对象模型》 侯捷 译