|
考虑如下代码:
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 functionclass派生自继承串链,其中有一个或更多的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);
}
|