考虑如下代码:
class Foo {
public:
int val;
Foo *extent;
}
void foo_bar()
{
Foo bar;
if(bar.val || bar.pnext){
}
}
上述代码语义是要求Foo 有一个default contructor 可以將它的两个members 初始化为0。可是编译器却不会为你做这件事情。
带有deafault constrcutor的member class object
如果一个class 没有任何constructor ,但它内含一个member object ,而后者有default constructor ,那么这个class 的implicit defautl constructor 就是nontrivial 编译器需要为该class 合成一个default constuctor 。考虑如下代码:
class Foo {
public:
int val;
Foo *extent;
Foo();
Foo(int) ...
}
class Bar {
public:
Foo foo;
char *str;
}
void foo_bar()
{
Bar bar;
if(bar.str){
}
}
被合成的Bar defautl constructor 内含必要的代码,能够调用class Foo 的default constructor 来处理member obejct Bar::foo ;被合成的default constructor 看起来像这样:
inline Bar::Bar() {
foo.Foo::Foo();
}
如果有多个class member objects 都要求constructor 初始化操作,将如何?C++ 语言要求以members objects 在class 中的声明顺序来调用各个constructors 。考虑如下代码:
class Dopey {public: Dopey();};
class Sneezy {public: Sneezy(); Sneezy(int);};
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 constuctors ,然后如果Snow_White 定义了如下的default constructor
Snow_White::Snow_White() : sneezy(1024) {
mumble = 2048;
}
它会被扩张为:
Snow_White::Snow_White() : sneezy(1024) {
dopey.Dopey::Dopey();
sneezy.Sneezy::Sneezy();
bashful.Bashful::Bashful();
mumble = 2048;
}
带有Default Constructor的Base Class
如果一个没有任何constructor 的class 派生自一个带有default constructor 的bass class ,那么这个derived class 的default constructor 会被视为nontrivial ,并因此需要被合成出来
带有一个Virtual Function的Class
另外有两种情况,也需要合成出default constructor
class 声明一个virtual function class 派生自继承串链,其中有一个或更多的virtual base classes
考虑如下代码:
class Widget {
public:
virtual void flip() = 0;
};
void flip(const Widget& widget) {widget.flip();}
void foo() {
Bell b;
Whistle w;
flip(b);
flip(w);
}
下面两个扩张行动会在编译期发生:
- 一个
virtual function table 会被编译器产生出来,内放class 的virtual functions 地址 - 在每个
class object 中,一个额外的pointer member 会被编译器合成出来,内含相关的class
带有一个Virtual Base Class的Class
class X {public : int i;};
class A : public virtual X{public : int j;};
class B : public virtual X{public : double d;};
class C : public A, public B {public : int k;};
void foo(const A *pa) {pa->i = 1024;}
int main() {
foo(new A);
foo(new C);
}
|