C++对象模型之默认构造器

带有Default Constructor的Member Class Object

如果一个类没有任何constructor,但它内含一个member object,而后者有default constructor,那么这个类的implicit default constructor就是nontrivial,编译器会为此合成出一个default constructor。只是这个合成操作只有在constructor真正需要被调用时才会发生。示例如下:

class Foo {public: Foo()};
class Bar {public: Foo foo; char * str; };

void func()
{
	Bar bar;  //此处Bar::foo必须要被初始化
}

于是编译器可能合成出以下default constructor:

inline Bar::Bar()
{
	foo.Foo::Foo();
}

可以看出编译器只合成出对member object进行初始化的default constructor,至于其他数据成员如str指针并没有被初始化,它的初始化程序应由程序员编写完成。于是程序员可以编写以下的default constructor:

Bar::Bar() {str = NULL;}

那么此时在已有default constructor的情况下,编译器该如何操作呢?没错,如果类中内涵一个或多个member objects,那么编译器会对每个已存在的constructors进行扩张,如下所示:

Bar::Bar()
{
	foo.Foo::Foo(); //扩张的代码
	//...如果有其他member objects,则按声明顺序进行扩展
	str = NULL;
}

带有Default Constructor的基类

如果一个没有任何constructor的类派生自一个带有default constructor的base class,那么这个派生类的default constructor会被视为nontrivial,因此需要进行合成,也就是调用基类的default constructor。同样当派生类已有多个非default的constructors时,编译器会对现有的每一个constructor进行扩张,将基类的default constructor添加进去。

带有一个Virtual Function的类

在编译期间会发生如下两个扩张操作:

  1. 一个virtual function table(vtbl)会被编译器产生出来,保存类的virtual function地址。
  2. 在每一个class object中,一个额外的pointer member(vptr)会被编译器合成,指向vtbl的地址。

为了使得上述操作生效,编译器必须为每一个派生类对象的vptr设定初值。对于类所定义的每一个constructor,编译器会插入一些代码来做这样的事情(详见《C++对象模型》5.2节)。

带有一个虚基类的类

如下代码:

class X {public: int n};
class A : public virtual X {...};
class B : public virtual X {...};
class C : public A, public B {public: int k; };

//无法在编译期间决定出pa->X::i的位置
void foo(const A* pa) { pa->n = 1024; }

void main ()
{
	foo(new A);
	foo(new C);
}

编译器无法固定住foo()之中“经由pa而存取的X::i”的实际偏移位置,因为pa的真正类型可以改变。编译器必须使X::i可以延迟到执行期才决定下来。通过使用reference或pointer来存取一个virtual base class可以实现该目标。于是上述操作被编译器转变如下:

//__vbcx就是编译器所产生的指针
void foo( const A* pa) { pa->__vbcx->n = 1024; }

这个指针也必须在构造期间进行初始化,所以编译器需要在每个constructor中插入初始化的代码。如果没有声明任何constructor,那么编译器必须为它合成一个default constructor。

总结

在看本节之前存在的误解:

  • 任何class如果没有定义default constructor,就会被合成出一个来。
  • 编译器合成出来的default constructor会明确设定“类内每一个数据成员的默认值”。

显然以上没有一个是正确的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值