c++构造函数详解
2015-07-16 23:43
435 查看
一、Default constructor
1. 对于class X ,如果没有任何user-declared
constructor,那么编译器生成的default constructor是无用的
2. 编译器合成(扩张)的default constructor 是有用的4中情况
①.带有default constructor的member
class object
Member class object 的Default constructor会在合成(扩张)的default
constructor调用。
②.带有default constructor的base
class
合成(扩张)的default constructor会调用base class的default
constructor
③.带有一个virtual funtion的class
合成(扩张)的default constructor会初始化类的vptr
④.带有一个virtual base class的class
3. 误区
①.任何class如果没有定义default
constructor,就会被合成出来。
②.编译器合成出来的default constructor 会被明确设定class内的每一个data
member的默认值。
二、Copy constructor
1. 有三种情况,会以一个object的内容作为另一个class的初值。
①.明确的以一个object的内容作为另一个class
object的初值 X xx = x;
②.当object被当作参数交给某个函数时 void
foo(X x)
③.当函数传回一个class object x = foo() { return
xx;}
如果定义了copy constructor则大多数情况下会被调用,否则其内部是以所谓的default memberwise initialization 手法完成,对于其中member
class object是以递归方式施行memberwise initialization。
2. 编译器会合成copy constructor的情况即class不表现出bitwise
copy semantics
①.当class内含一个member
object而后者的class声明有一个copy constructor时(具备条件合成的)
②.当class继承自一个base
class而后者存在有一个copy constructor(被明确声明或被合成)
③.当class声明了一个或多个virtual
funtions时
④.当class派生自一个继承串链,其中有一个或多个virtual
base classes时
下面对第三点做简要说明:
我们知道编译期间的两个程序扩张操作(有virtual funtion存在的前提下)
I.增加一个virtual function table(vtbl),内含每一个有作用的virtual
function的地址
II.将一个指向virtual function table的指针(vptr),安插在每一个class
object内
从这两点我们可以看出编译器需要合成出一个copy constructor以求将vptr适当的初始化。
class ZooAnimal
{
public:
ZooAnimal(){}
virtual ~ZooAnimal(){}
virtual void animate(){}
virtual void draw() {}
};
class Bear : public ZooAnimal
{
public:
Bear(): b(5){memset(this, 0, sizeof(Bear));}
virtual void animate(){}
virtual void draw() {}
virtual void dance(){}//父类没有的虚函数
};
Bear yogi;
Bear winnine = yogi;
这种情况下yogi的vptr值拷贝给winner的vptr是安全的,也就说此时两个对象的vptr完全一样。
但是下面这种情况
ZoonAnimal franny = yogi;
此时franny的vptr不可以被设定指向Bear
class的virtual table。也就说合成出来的ZoonAnimal copy constructor会明确设定object的vptr指向ZoonAnimal
class的virtual table,而不是直接从右手边的class object将其vptr现值拷贝过来
三、成员初值列(member initialization list)
1. 为了通过编译必须使用member initialization list的情况
① 当初始化一个reference member
② 当初始化一个const member
③ 当调用一个base class的constructor,而它拥有一组参数时
④ 当调用member class的constructor,而它拥有一组参数时
初始化顺序不是有list中的项目顺序而是有member声明次序决定;编译器会一一操作initialization
list根据声明次序在constructor内安插初始化操作,并且在任何explicit user code之前。
1. 对于class X ,如果没有任何user-declared
constructor,那么编译器生成的default constructor是无用的
2. 编译器合成(扩张)的default constructor 是有用的4中情况
①.带有default constructor的member
class object
Member class object 的Default constructor会在合成(扩张)的default
constructor调用。
②.带有default constructor的base
class
合成(扩张)的default constructor会调用base class的default
constructor
③.带有一个virtual funtion的class
合成(扩张)的default constructor会初始化类的vptr
④.带有一个virtual base class的class
3. 误区
①.任何class如果没有定义default
constructor,就会被合成出来。
②.编译器合成出来的default constructor 会被明确设定class内的每一个data
member的默认值。
二、Copy constructor
1. 有三种情况,会以一个object的内容作为另一个class的初值。
①.明确的以一个object的内容作为另一个class
object的初值 X xx = x;
②.当object被当作参数交给某个函数时 void
foo(X x)
③.当函数传回一个class object x = foo() { return
xx;}
如果定义了copy constructor则大多数情况下会被调用,否则其内部是以所谓的default memberwise initialization 手法完成,对于其中member
class object是以递归方式施行memberwise initialization。
2. 编译器会合成copy constructor的情况即class不表现出bitwise
copy semantics
①.当class内含一个member
object而后者的class声明有一个copy constructor时(具备条件合成的)
②.当class继承自一个base
class而后者存在有一个copy constructor(被明确声明或被合成)
③.当class声明了一个或多个virtual
funtions时
④.当class派生自一个继承串链,其中有一个或多个virtual
base classes时
下面对第三点做简要说明:
我们知道编译期间的两个程序扩张操作(有virtual funtion存在的前提下)
I.增加一个virtual function table(vtbl),内含每一个有作用的virtual
function的地址
II.将一个指向virtual function table的指针(vptr),安插在每一个class
object内
从这两点我们可以看出编译器需要合成出一个copy constructor以求将vptr适当的初始化。
class ZooAnimal
{
public:
ZooAnimal(){}
virtual ~ZooAnimal(){}
virtual void animate(){}
virtual void draw() {}
};
class Bear : public ZooAnimal
{
public:
Bear(): b(5){memset(this, 0, sizeof(Bear));}
virtual void animate(){}
virtual void draw() {}
virtual void dance(){}//父类没有的虚函数
};
Bear yogi;
Bear winnine = yogi;
这种情况下yogi的vptr值拷贝给winner的vptr是安全的,也就说此时两个对象的vptr完全一样。
但是下面这种情况
ZoonAnimal franny = yogi;
此时franny的vptr不可以被设定指向Bear
class的virtual table。也就说合成出来的ZoonAnimal copy constructor会明确设定object的vptr指向ZoonAnimal
class的virtual table,而不是直接从右手边的class object将其vptr现值拷贝过来
三、成员初值列(member initialization list)
1. 为了通过编译必须使用member initialization list的情况
① 当初始化一个reference member
② 当初始化一个const member
③ 当调用一个base class的constructor,而它拥有一组参数时
④ 当调用member class的constructor,而它拥有一组参数时
初始化顺序不是有list中的项目顺序而是有member声明次序决定;编译器会一一操作initialization
list根据声明次序在constructor内安插初始化操作,并且在任何explicit user code之前。
相关文章推荐
- 使用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++ Custom Control控件向父窗体发送对应的消息
- C++中拷贝构造函数的应用详解