标签:his 整数 默认 对象模型 没有 无法 function point 函数
我们通常会说当生命一个 class 时,如果我们不为该 class 指定一个 constructor,那么编译器会替我们实现一个 connstructor,那么这种说法一定对吗?
事实上,这是不对的。这个不是我说的,是深入理解C++对象模型说的,原话是:
C++新手一般有两个常见的误解:
下面分别讨论上述四种合成 constructor 的情况:
class Foo { public: Foo(), Foo( int ) ... };
class Bar { public: Foo foo; char* str; }; //不是继承,是包含
void foo_bar(){
Bar bar; //Bar::foo 必须在此处初始化
//译注:Bar::foo是一个member object,而其 class Foo 拥有default constructor,符合本小节主题
if( str ) { } ...
}
此时 class Bar 内含一个 member object Foo,并且 Foo 有 default constructor Foo(),那么编译器就会为 Bar 合成一个 default constructor,看起来像这样:
//Bar 的 default constructor 可能会这样合成
//被 member foo 调用 class Foo 的 default constructor
inline
Bar::Bar(){
//C++伪码
foo.Foo::Foo();
}
Bar::Bar() { str = 0; } //程序员定义的 default constructor
此时编译器还需要初始化 member object foo,但是由于 default constructor 已经被程序员明确定义出来了,编译器没办法合成第二个。编译器采取的行动是:“如果 class A 内含一个或一个以上的 member class object,那么 class A 的每一个 constructor 必须调用每一个 member classes 的 default constructor”,编译器会向用户程序员的 constructors 前面插入必要的 default constructor。插入后可能像这样:
//插入后的 default constructor
//C++伪码
Bar::Bar(){
foo.Foo::Foo(); //插入的 compiler code
str = 0; //explicit user code
}
如果有多个 class member objects 都要求初始化操作,将如何做呢?C++会按照 “member objects 在 class 中的声明次序“ 来调用各个 consructors。这一点由编译器完成。并且如果某个 member object 的 default constructor 被程序员定义过了,它照样会被按顺序调用。如:
//程序员对 Snow_White 类所写的 default constructor,显示初始化一个 member object
Snow_White::Snow_White() : sneezy( 1024){
mumble = 2048
}
它会被扩张为:
Snow_White::Snow_White() : sneezy( 1024) {
//插入 member class onject
//调用其 constructor
dopey.Dopey::Dopey();
sneezy.Sneezy::Sneezy(1024);
bashfun.Bashfun::Bashful();
//explicit user code
mumble = 2048;
}
如果一个 class 声明或继承一个 virtual function,并且缺乏由用户声明的 constructors,编译器会详细记录合成一个 default constructor 的必要信息。如:
class Widget{
public:
virtual void filp() = 0;
...
}
void filp( const Widget& widget ) { widget.filp(); }
//假设 Bell 和 Whistle 都派生自 Widget
void foo(){
Bell b;
Whistle w;
filp( b );
filp( w );
}
下面两个扩张步骤在编译期间发生:
//widget.filp() 的虚拟引发操作(virtual invocation)的转变 // (* widget.vptr[ 1 ] )( &widget )
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, pulic B { public: int k; };
//无法在编译使其决定(resolve)出pa->X::i 的位置
void foo( const A* pa) { pa->i = 1024; }
main()
{
foo( new A );
foo( new C );
// ...
}
//可能的编译器转变操做,中间加了一层
void foo( const A* pa ) { pa->__vbcX->i = 1024; }
标签:his 整数 默认 对象模型 没有 无法 function point 函数
原文地址:http://www.cnblogs.com/wangsicongde/p/7599188.html