Default Constructor 的建构操作

default constructor 会在需要的时候被编译器产生出来 

----<<Inside C++ Object Model>>

一切从这开始, 是在谁需要的时候? 考察以下代码:


class Foo{public: int val; Foo *pnext};


void FooBar()
{
//Foo Object 须在此初始化
Foo bar;
if(bar.val || bar.pnext)
//do something...
}


编译器不会为其产生一个 default constructor, 因为这是程序需要而不是编译器需要, 程序有需要, 那是程序员的责任, 因此上述代码不会合成一个 default constructor.


那么在那些情况下是编译器需要构建 default constructor 的情况呢?


1. 带有 Default Constructor 的 Member Class Object
但出现一个问题, 怎样防止在不同模块中生成多个 default constructor?
解决方法是, 把合成的 default constructor 都以 inline 的方式完成, inline 函数有静态连接, 不会被文件以外看到, 如果函数太复杂, 不适合做出一个 inline, 编译器则会做出一个 explicit non-inline static 实体. 考察以下代码:


class Foo{public: Foo(){} Foo(int){/* do something */}...};
class Bar{private: Foo foo; char *pstr;};


void FooBar()
{
//bar Object 需要在此初始化
Bar bar


if(str)...
}


此例中, 编译器会产生 bar 的 default constructor 来调用 class Foo 的 default constructor 初始化 Bar::foo, bar 的 default constructor 中, 并不存在初始化 str 的代码, 因为那是程序员的责任.


那么如果程序员已定义了用来初始化 str 的 constructor, 如:
Bar::bar(){str = 0;}


那么编译器会怎样做呢, 它会扩展你的代码, 在你的代码之前添加必要的 default constructor 即:
//你看上去的
Bar::bar(){str = 0;}


//实际可能是
Bar::bar(){Foo::Foo(); str = 0;}


问题又来了, 假如 class 中 有多个 member object 嗷嗷待哺呢?
结果是, 编译器会按照其声明的顺序初始化.


2. 带有 Default Constructor 的 Base Class
我倾向于用一个例子说明问题:


class Member{public: Member(){std::cout << "member ";}} 


class Base1 {
public: Base1(){public: std::cout << "base1";}
private: Member m;};


public: Base2(){public: std::cout << "base2";}
private: Member m;};


class Derived:public Base2, public Base1
{public: Derived(){std::cout << "derived";}}


int main(){Derived d; return 0;}


输出结果是: 
member      //由程序员定义的 Base2::Base2() 被扩展
base2       //由此可见, 调用顺序由继承顺序有关
member 
base1
derived     //编译器扩展的代码结束, user code 开始运行


前四段代码是编译器在用户定义的 constructor 代码中, std... 之前插入的调用 base constructor 的代码产生的结果, 按照继承的顺序调用相应的 constructor.


3. 带有 Virtual Function 的 Class
在带有 virtual function 的 class 中, 如果缺少合适的 constructor, 编译器会进行两个扩张:
1) 一个 virtual function table 会被创建出来, 内放 class 的 virtual
function 地址
2) 在每一个 class object 中, 一个额外的 pointer member(即 vptr) 会被创建出来, 内含相关的 vtbl 地址
所以编译器会产生一个 default constructor 来初始化 vtbl 与 vptr


4. 带有Virtual Base Class 的 Class
考察以下代码:
struct X{int i;};
struct A:public virtual X{int j;};
struct B public virtual X{int k;};
struct C:public A, public B{double d;} 


void Foo(const A *pa){pa->i = 1024;}


int main()
{
Foo(new A);
Foo(new C);
}


编译器无法确定 Foo() 中 _i 的实际 _i 移动的位置, 因为 pa 可以改变, 要延迟到执行期才能固定下来, 因此此动作要通过存取 virtual base class 的相关指针来完成, 因此编译器实际可能做的事情是把函数扩充为:
void Foo()(const A *pa){pa->__vbcX->i = 1024;}


没错, 那么 __vbcX 就需要在 object 被建构之前被初始化, 编译器就需要为它合成一个 default constructor.


新手的误解:
1) 若 class 没有定义一个 default constructor, 那么编译器就会合成一个出来;


2) 编译器合成出来的 default constructor 会明确设定 class 内每一个 data member 的初始值.


当然, 以上观念都是错的!
原文地址:https://www.cnblogs.com/wuOverflow/p/4098671.html