C++构造函数语意学 - Constructor(The Semantics of Constructors)
2015-10-24 16:29
465 查看
1.默认构造函数(Default Constructor)
default constructors 在编译器需要时被合成出来。被合成出来的constructor只执行编译器所需的行动。也就是说default constructor不会将data members(如 int型)初始化,而是处理member object(成员对象)等编译器的需求。对于class X ,如果没有任何user-declated constructor,那么会有一个default constructor被隐式声明出来,一个被隐式声明出来的default constructor将是一个trivial(没啥用的) constructor
2.由编译器合成constructor或改造user-declated constructor的四种情况
①带有Default Constructor 的 Member Class Object如果一个class没有任何constructor,但它内含一个member object,而后者有default constructor,那么这个class的implicit default constructor就是nontrivial.
例:
#include <iostream> class A{ public: A(){ printf("A Constructor\n"); } }; class B{ public: int i; A a;//class A中有Default Constructor }; int main(int argc, const char * argv[]) { B b;//此时B的constructor调用了A的constructor printf("%d\n",b.i);//实际输出为0,可能是由于编译器优化。 return 0; } 输出: A Constructor 0
class B被合成的Default Constructor可能是这样:
B::B(){ a.A::A(); }
假如定义了B的constructor如下
B::B(){ i = 100; }
编译器将会改写B的constructor如下
B::B(){ a.A::A();//将按声明顺序先调用class member objects的construct i = 100;//再调用用户所写的代码(explicit user code) }
②带有Default Constructor的Base Class
例:
#include <iostream> class A{ public: A(){ printf("A Constructor\n"); } }; class B: public A{ public: int i; }; int main(int argc, const char * argv[]) { B b;//此时B的constructor调用了A的constructor return 0; } 输出: A Constructor
详情与①类似,如果同时存在有Default Constructor的Base Class和 Member Class Object,将先按顺序的调用Base Class的Default Constructor,再调用Member Class Object的Default Constructor。
③带有virtual Function 的 class
编译器会发生两个扩张行动在编译期间:
1.一个virtual function table(vtbl)会被编译器产生出来,内放class的virtual functions地址
2.在每一个class object中,一个额外的pointer member(就是vptr)会被编译器合成出来,内含相关之class vtbl的地址
此外虚拟调用操作将会被改写
virtualBaseClassObject.virtualFun()
会被改写成:
(*virtualBaseClassObject.vptr[1])(&virtualBaseClassObject)
1表示virtualFun()在virtual table中的固定索引值。
&virtualBaseClassObject表示调用virtualFun()的实例的this指针。
④在Virtual Base Class的Class
#include <iostream> class X{ public: int i; }; class A:virtual public X{ public: int j; }; class B: virtual public X{ public: int k; }; class C: public A, public B{ public: int g; }; //无法在编译时期决定pa的类型和pa->X::i的位置 void foo(A* const pa){ pa->i = 1024; } int main(int argc, const char * argv[]) { foo(new A); foo(new C); return 0; }
编译器将
void foo(A* const pa){ pa->i = 1024; }
转化为
void foo(A* const pa){ pa->_vbcX->i = 1024; }
其中_vbcX表示编译器所产生指向virtual base class X的指针
而_vbcX是在class object构造期间被完成的,编译器会安插这些代码在constructor中。
3.常见的两个误解:
1.任何class如果没有定义default constructor,就会合成一个2.编译器合成出来的default constructor会显示的设定class内每一个data member的默认值。(某些编译器会优化,为每一个data member赋默认值,然而这不是c++标准所定义的)
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C与C++之间相互调用实例方法讲解
- 解析C++中派生的概念以及派生类成员的访问属性
- C++ Custom Control控件向父窗体发送对应的消息