第2章构造函数语义学读书笔记——深度探索c++对象模型

第2章 构造函数语义学

2.1 Default Constructor的构建操作

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

void foo_bar(){
   
    // 程序需要bar's members都被清零
    Foo bar;
    if(bar.val || bar.pnext)
       // ...do something
}

上面例子中,程序语义需要Foo有一个default constructor,可以将它的两个members初始化为0。但是上述程序并不会合成一个default constructor。

Q:什么时候才会合成一个default constructor?

Ans:当编译器需要它的时候!此外,被合成的constructor只执行编译器所需的行动。为了让上一段程序正确运行,必须提供一个明显的default constructor,将两个members适当的初始化。

对于class X,如何没有任何的user-declared constructor,那么会有一个default constructor被暗中(implicitly)声明出来……一个被暗中声明出来的default constrtuctor将是一个trivial(没用的) construct……被编译器需要的是nontrivial default constructor。

下面讨论nontrivial default constructor的四种情况。

1.“带有Default Constructor"的Member Class Object

如果一个class没有任何constructor,但它内含的一个member object有default constructor,那么这个class的implicit default constructor就是”nontrivial“,编译器需要为此class合成出一个default constructor,不过这个合成操作只有在constructor真正需要被调用时才会发生。

class Foo {
    public: Foo(), Foo(int)...};
class Bar {
    public: Foo foo; char *str;} //不是继承,是内含

void foo_Bar(){
   
    //Bar::foo是一个member object,其class Foo拥有default constructor
    Bar bar; //Bar::foo必须在此初始化。
    if(str){
    }...
}

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

// 被member foo调用class Foo的default constructor
inline Bar::Bar()
{
   
    //c++伪代码
    foo.Foo:Foo();
}

上面只是满足了编译器的需要,而不是程序的需要。为了让程序正常执行,字符指针str也需要被初始化。

//程序员定义的default constructor
Bar::Bar() {
    str=0;}

此时编译器采取的行动:”如果class A内含一个或一个以上的member class objects, 那么class A的每一个constructor必须调用每一个member classes的default constructor“。编译器会扩张已存在的constructors,在其中安插一些代码,使得user code被执行前,先调用必要的default constructors.

//扩张后的default constructor
//c++伪码
Bar::Bar()
{
   
    foo.Foo::Foo(); //附加上的complier code
    str = 0;
}

再举一例:

class Dopey {
   public: Dopey(); ...};
class Sneezy {
   public: Sneezy(int); Sneezy(); ...};
class Bashful {
   public: Bashful(); ...}

class Snow_White{
   
public:
    Dopey dopey;
    Sneezy sneezy;
    Bashful bashful;
    //....
private:
    int mumble;
};

如果Snow_White没有定义default constructor,就会有一个nontrivial constructor被合成出来,依次调用dopey、sneezy、bashful的default constructors,如果Snow_White定义了下面这样的default constructor:

//程序员写的
Snow_White::Snow_White():sneezy(1024){
   
    mumble=2048;
}

它会被扩张为

Snow_White::Snow_White():sneezy(1024){
   
    //插入member class object,调用其constructor
    dopey.Dopey::Dopey();
    sneezy.Sneezy::Sneez
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值