先引用《深度探索C++对象模型》中的一段话:
C++ 新手一般有2个误解
1 任何class如果没有定义default constructor,就会被合成出一个来
2 编译器合成出来的default constructor会显示设定class类每一个data member的默认值。
如你所见,没有一个是真的。
有下列4种情况,编译器必须会未声明的constructor合成一个“default constructor”, 被合成出来的constructor只能满足编译器需要而不是程序需要。
1 "带有Default Constructor"的member class object
class Foo{
public:
Foo();
Foo(int);
};
class Bar
{
public:
Foo foo;
char *str;
};
这种情况下,编译器会为class Bar 合成一个default constructor,被合成的default constructor内含必要的代码,能够调用class Foo的default constructor来处理Bar::foo。至于*str的初始化(程序的需要),编译器并不会管。
伪代码:
inline Bar::Bar()
{
foo.Foo::Foo();
}
但是如果Bar已经显示定义了一个默认构造函数,比如
Bar() { str = nullptr; }
现在程序的需求已经满足了,但是编译器还需要初始化member object foo。这是,编译器不能定义default constructor了,只能在程序员定义的构造函数安插一些代码,确认user code被执行之前,先调用default constructor。类似伪代码:
Bar {
/*
插入的代码
foo.Foo::Foo();
*/
str = nullptr;
}
class A { public A() { } };
class B { public B(int) { } };
class C { public C() { } };
class D {
public:
D(): b(int) { }
public:
A a;
B b;
C c;
};
这种情况是D的构造函数会被改造为:
D():b(int) {
a.A::A();
b.B::B(int);
c.C::C();
// 其他
}
注意顺序是按照声明顺序来的。
2 "带有Default Constructor"的Base Class
类似道理,如果没有任何constructors的class继承自一个带有Defaultor Constructor的Base class, 那么derived class的default constructorh会被合成出来,调用Base class的defaultor constructor。
3 "带有Virtual Function"的Class
class Widget
{
public:
virtual void flip() = 0;
};
class Bell : public Widget {......}
class Whistle : public Widget {......}
void flip(const Widget& widget) { widget.flip(); }
void foo() {
Bell b;
Whistle w;
filp(w);
filp(b);
}
下面2个行为会在编译期间发生:
- 一个virtual function table(vptl)会被编译器产生出来,里面放class 的virtual function的地址。
- 在每一个class object中,一个额外的pointer member(vptr)会被产生出来,内含vtbl地址。
这一段可以结合另外2篇文章理解:
C++ 对象模型分析
C++ 虚函数表分析
4 "带有一个Virtual Base Class"的Class
这块还不熟悉,待更。