构造函数语义学---default constructor

C++ Annatated Reference Manual告诉我们:“default construct会在需要的时候被编译器产生出来”。关键字眼在于什么时候需要以及被谁需要。一般说来,default construct的需求方有程序员和编译器。如果程序员需要,那么他就有责任在程序中声明construct function。如果是编译器需要,那么编译器就会在程序中合成construct。当然,合成construct只会执行编译器需要的行动。下面讲一下编译器合成的default construct有效的四种情况:

1)带有“default constructor”的menber class object

如果一个类没有任何construct,但它含有一个member object,而后者有default construct,那么这个class的implict default construct就是“nontrival”,编译器需要为此合成一个default constructor.不过这个合成操作只有在constructor真正调用时才会发生。

一个有趣的问题就发生了,编译器如何避免在不同的编译模块中合成出多个default constructor?就解决方法就是把合成的default construct ,destructor,assigment copy operator都已inline的方式完成。一个inline函数都有静态链接,不会被档案以外的部分看到。

举个例子,在下面的程序中,编译器为class Bar合成一个default constructor:

class Foo{

      public;

                Foo();

                 Foo(int );

}

class Bar{

    public:

          Foo foo;

    char *str;



}

void foo_bar(){

        Bar bar;//必须再次初始化

       if(str){

     

}

}

被合成的Bar default constructor 内含有必要的代码,能够调用Foo default constructor来处理membert object Bar::foo,但它并不产生任何代码来初始化Bar::str。将Bar::str初始化是程序员的责任,将Bar::foo初始化时编译器的责任。被合成的default constructor看起来像这样:

inline Bar::Bar(){

        foo.Foo::Foo();

}

再一次注意,被合成的default construct是编译器的需要,而不是程序员的需要。为了能让这个程序片段真正运行起来,字符串str也需要被初始化。假设程序员经由下面的default constructor提供str的初始化操作:

Bar::Bar(){

     str=0;

}

现在程序的需求满足了,但是编译器还需要初始化member object foo,由于default constructor已经被明确定义出来了,编译器没办法合成第二个。编译器采取的行动是将初始化foo的代码插入到Bar default constructor中,使得用户代码在执行之前先调用必要的default constructor,扩大后的代码可能是:

Bar::Bar(){

       foo.Foo::Foo();//附加的编译器代码

       str=0;//explict user code

}

如果有多个class member object 都要求construct初始化操作,编译器将如何做呢?c++语言要求以“ member object”在class中的声明次序来调用各个construct,这一点由编译器来完成。它会为每一个member object安插程序代码,以“member声明次序”调用每一个member object的default constructor,这些代码将会被安插在explict user code之前。举个例子

class Dopey{

public:

Dopey();

}

class Sneezy{

public:

Sneezy();

Sneezy(int );

}

class Snow_white{

        public:

    Dopey dopey;

    Sneezy sneezy;

private;

int number;

}

如果class Snow_white没有定义default constructor,编译器就会合成一个nontrival constructor被合成出来。然而,Snow_white定义了下面的default constructor。

Snow_white::Snow_white();sneezy(1023){

     number=2045;

}

它会被扩张如下:

Snow_white::Snow_white();sneezy(1023){

     //插入member class object

   dopey.Dopey::Dopey();

   sneezy.Sneezy::Sneezy(1024);

//explict user code

    number=2045;

}

2)带有default constructor的Base Class

如果一个没有任何constructor的class派生自一个带有“default constructor”的base class,那么derive class的default constructor会被是为nontrivial,并因此需要被合成出来。他将调用上一层base class的default constructor(按照他们的声明次序),对一个后继派生的class而言,这个合成的construtor和一个被明确提供的default constructor没有什么差异。

如果设计者提供多个constructor,但其中都没有Base Class的default constructor呢?编译器会扩张现有每一个constructor,将所有用以调用必要的dafault constructor的代码加进去,它不会合成一个新的default constructor,这是因为其它由“user 所提供的constructor存在的缘故”,如果同时存在“带有default constructor”的membe class object,那些default constructor也会被调用----在所有base class constructor都被调用之后。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值