欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

《深入探索C++对象模型》第二章 构造函数语义学(The Semantics of Constructors)

程序员文章站 2024-03-21 12:36:28
...

一、default constructor的构造操作

先看一个小例子:

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

此处正确的程序语意是要求Foo有一个默认构造函数,能将它的两个成员初始化为0,那么编译器会为我们合成这样的默认构造函数吗?答案是不会!(事实上,这里合成的默认构造函数是trival的构造函数,也就是它什么也不干,连初始化也不干。在概念上我们把这种构造函数叫做implicit trival default constructors,但实际上这种构造函数根本不会被合成出来)。这是因为初始化成员是程序的需要,而不是编译器的需要,本例中要承担成员初始化责任的是设计者。

在四种情况下,non-trival default constructor会被编译器合成出来,下面一一讨论这四种情况。

1. 带有Default constructor的Member Class Object

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

这就引出一个问题,在C++的各个不同的文件中,编译器如何避免合成出多个default constructor?解决办法是把合成的default constructor、copy constructor、deconstructor,copy assignment operator都以inline方式完成,一个inline函数具有静态链接,不会被文件以外者看到。如果函数太复杂不适合做成inline,就会合成出一个explicit non-inline static实例。(这一段没太明白)

下面是一个小例子:

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

void foo_bar()
{
    Bar bar;   //Bar::foo在这里必须被初始化

    if( str ) { }...
}

在本例中,编译器将为class Bar合成一个default constructor,内含必要的代码,能够调用class Foo的default constructor来处理member object Bar::foo,但是要注意,这个default constructor依然不会负责str的初始化!

未完待续...