C++ - 对象模型之 构造和析构函数都干了什么

转自: http://blog.csdn.net/gykimo/article/details/8629896


C++ - 对象模型之 构造和析构函数都干了什么


我们知道,编译器背着我们做了很多其他的事情,这些事情最为复杂的就是构造函数、拷贝构造函数和析构函数。本部分主要分析,编译器给构造函数、析构函数等都增加了什么功能。


构造和析构函数


无继承

如C++代码:
  1. class Toy  
  2. {  
  3. public:  
  4.     Toy(){};  
  5.     virtual ~Toy(){}  
  6.   
  7. private:  
  8.     virtual void play(){printf("play the toy\n");}  
  9. };  
  10.   
  11. class Child  
  12. {  
  13. public:  
  14.     Child():Age(10),name("小明"){}  
  15.     virtual void who(){printf("I am child\n");}  
  16.     virtual ~Child(){}  
  17.   
  18. private:  
  19.     int Age;  
  20.     Toy toy;  
  21.     char* name;  
  22. };  
  23.   
  24. int main(){  
  25.     Child child;  
  26. }  

可能会被转化为如下伪码:
  1. Child::Child(){  
  2.     //设置vptr  
  3.     this->__vptr_Child = __vtbl_Child;  
  4.     //初始化列表  
  5.     Age = 10;  
  6.     name = "小明";  
  7.     toy::Toy();  
  8. }  
  9.   
  10. Child::~Child(){  
  11.     toy::~Toy();  
  12. }  
  13.   
  14. int main(){  
  15.     Child child;  
  16.     child::Child();  
  17.   
  18.     child::~Child();  
  19. }  

可见至少要做如下几件事情:

构造函数
1. 如果有虚函数,那么先设定vptr指向应该指向的vtbl;
2. 出现在初始化列表中的初始化操作会在构造函数中执行;
3. 如果member object有Default构造函数,即使没有出现在初始化列表中,也要在构造函数中调用该member的构造函数;

析构函数:
1. 如果member object有析构函数,那么要在析构函数中调用该member的析构函数进行析构;

继承

  1. #include <stdio.h>  
  2. #include <typeinfo.h>  
  3.   
  4. class GrandFather  
  5. {  
  6. public:  
  7.     GrandFather(){who();}  
  8.     virtual void who(){printf("I am GrandFather\n");}  
  9.     ~GrandFather(){who();}  
  10.     void func(){}  
  11. };  
  12.   
  13.   
  14. class Father : public GrandFather  
  15. {  
  16. public:  
  17.     Father(){who();}  
  18.     ~Father(){who();}  
  19. };  
  20.   
  21. class Child : public Father  
  22. {  
  23. public:  
  24.     Child(){who();}  
  25.     virtual void who(){printf("I am child\n");}  
  26.     virtual ~Child(){who();}  
  27.   
  28. private:  
  29.     int Age;  
  30. };  
  31.   
  32. int main(){  
  33.     Child child;  
  34. }  

伪码:
  1. class GrandFather  
  2. {  
  3. public:  
  4.     GrandFather(){  
  5.         //设置vptr  
  6.         this->__vptr = __vtbl_GrandFather;  
  7.         who();  
  8.     }  
  9.     virtual void who(){printf("I am GrandFather\n");}  
  10.     ~GrandFather(){  
  11.         //设置vptr  
  12.         this->__vptr = __vtbl_GrandFather;  
  13.         who();  
  14.     }  
  15. };  
  16.   
  17.   
  18. class Father : public GrandFather  
  19. {  
  20. public:  
  21.     Father(){  
  22.         GrandFather::GrandFather();  
  23.         //设置vptr  
  24.         this->__vptr = __vtbl_Father;  
  25.         who();  
  26.     }  
  27.     ~Father(){  
  28.         //设置vptr  
  29.         this->__vptr = __vtbl_Father;  
  30.         who();  
  31.         GrandFather::~GrandFather();  
  32.     }  
  33. };  
  34.   
  35. class Child : public Father  
  36. {  
  37. public:  
  38.     Child(){  
  39.         Father::Father();  
  40.         //设置vptr  
  41.         this->__vptr = __vtbl_Child;  
  42.         who();  
  43.     }  
  44.     virtual void who(){printf("I am child\n");}  
  45.     virtual ~Child(){  
  46.         //设置vptr  
  47.         this->__vptr = __vtbl_Child;  
  48.         who();  
  49.         Father::~Father();  
  50.     }  
  51.   
  52. private:  
  53.     int Age;  
  54. };  
  55.   
  56. int main(){  
  57.     Child child;  
  58.     child::Child();  
  59. }  

结果:
I am GrandFather
I am GrandFather
I am child
I am child
I am GrandFather
I am GrandFather

分析:
1. 构造函数先调用base的构造函数,后设置其他变量,包括vptr;
2. 构造函数调用虚函数,会调用它的vptr设置的虚函数,也就是说vptr的该虚函数。该案例,在对象创建过程中,who()会依次调用GrandFather的who(),然后是Father的,由于Father没有重写who,所以调用的还是GrandFather的,最后到了child,调用的是child的who,也就是在创建过程中,对象的类型依次是GrandFather、Father、Child;
3. 析构函数,会首先设置vptr,最后,才调用base的析构函数。所以,在析构过程中,对象的类型,依次是Child、Father、GrandFather;

赋值操作

还记得复制构造函数的bitwise copy吗?赋值操作也有bitwise copy,只要不满足下面的四种情况,对象赋值时,就采用bitwise copy:

1. 内有member object,并且该member class定义了copy assignment operator;

试想,如果我们还是使用bitwise copy,那么该member的copy assignment operator将不会被调用。

2. base class有copy assignment operator

3. 声明了任何的virtual functions

如果一个无继承的类,有virtual functions,是否也不满足bitwise copy呢?我认为,这个时候应该可以进行bitwise copy

4. 继承一个virtual base class


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值