构造函数语义学之Copy Constructor构建操作(2)

二、详述条件 3 和 4

  那么好,我又要问大家了,条件1 和 2比较容易理解。因为member object或 base class 含有copy constructor。那么member object所在的class或者base class的derived class需要合成一个nontrivial copy constructor来调用他的member constructor 或 base class的 copy constructor!

  而条件 3 和条件 4比较难理解,我在此阐述一下:

  (1) 条件3---当声明一个或多个virtual functions时

    大家回忆一下,在满足条件 3 时(class 声明了至少一个 virtual function),编译期间的两个程序扩张操作!

    1).增加一个virtual function table ,内涵每一个有作用的function的地址。

    2).将一个指向 virtual function table 的指针(vptr),安插在每一个class object 内。

  好,下面看我一个程序:

  

 1 #include <iostream>
 2 #include <string>
 3 using namespace std;
 4 
 5 class A0
 6 {
 7 public: 8     virtual void fun(){ cout << "I belong to A0!" << endl;}
9 };
10 
11 class A: public A0
12 {
13 public:
14     virtual void fun(){ cout << "I belong to A!" << endl;}
15 };
16 
17  int main()
18  {
19     A a;20     A b = a;21     return 0;
22  }

  大家看看代码中的第 21 行是不是将 a 赋值给了b,那么 a 中的指针 vptr 是不是 bitwise copy 给了 b 的指针 vptr 呢?答案是肯定的!但是这回指针的bitwise copy 是安全滴。为什么呢?因为同一类型的类实体中的 vptr 在内存中本身就是共享同一个 virtual function table的,请看下面一个图!

    图1 :这张补充说明了程序中 a 和 b 的关系,

  说到这里大家肯定要说了,这个用bitwise copy semantic完成不就可以了?为什么还要合成一个copy constructor来完成呢?对,如果仅仅是对付上面代码啦bitwise copy semantic足矣,但是我把上面代码中的main函数中的内容变一下:、

 

 1 #include <iostream>
 2 #include <string>
 3 using namespace std;
 4 
 5 class A0
 6 {
 7 public:
 8      9     virtual void fun(){ cout << "I belong to A0!" << endl;}
10 };
11 
12 class A: public A0
13 {
14 public:
15     virtual void fun(){ cout << "I belong to A!" << endl;}
16 };
17 
18  int main()
19  {
20     A a;
21     A0 a0 = a;
22     A0 *pa0;
23     pa0 = &a;
24     pa0->fun();
25     pa0 = &a0;
26     pa0->fun();
27     return 0;
28  }

 

  运行结果大家自己测试,如果此时,还是仅仅通过简单的bitwise copy semantic的话。那第 24 行中的pa0->fun()将会调用的是 a的fun()输出,I belong to A!这显然已经不满足类的多态性了嘛!说到这想必大家已经猜到一二了吧?对,此时编译器对类 A0 的对象不能bitwise copy semantic了,而是合成一个copy constructor进行一些必要的操作---包括对程序员定义的 member 的 bitwise copy (浅拷贝)和 对编译器安插的 vptr 进行重新赋值,即指向子类上例中的 A0 class 的 virtual table!很难理解?请看下图:

      图2 :补充说明 a0 和 a 的关系

  对比一下图 1 和图 2,就知道为什么 bitwise copy semantic不行了,而必须要合成一个copy constructor进行进一步操作了吧?

 

  (2)条件4---当class派生自一个继承串链,其中有一个或多个virtual base classes时

  如果你看懂了,条件 3 那么条件 4 这个也能很快就懂了!大家还记不记得我在我的另一篇博文(构造函数语义学之Default Constructor构建操作)中讲到 virtual base class时讲到:“编译器会为虚继承的derived class中安插一个指针 (vbptr)---用来指向virtual base class pointer table,这个表用来描述从继承类元素到虚基类元素的偏移量。”,既然如此,这和条件3是不是很像呢?也是安插了一个指针,那是不是也不能要bitwise copy constructor 呢?答案是肯定的!因为,这个 vbptr 指针 以及 virtual base class pointer table在内存中如何布局我们还没讲到,这里大家只要知道编译器安插了一个指针,该指针在复制时不能简单的 bitwise copy constructor就行了。剩下的,我会在后来的博文中阐述清楚!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值