首页 > 代码库 > 有关C++虚拟继承的简单理解

有关C++虚拟继承的简单理解

   最近在看《深度探索C++对象模型》这本书的时候,里面第一章提到了虚拟继承,有这么一句话说:“在虚拟继承的情况下,base class不管在继承串链中被派生多少次,永远只会存在一个实体。”一开始我理解错了,以为这个继承类图体系里面全局只有一个base class对象,后来查了些资料才知道意思是一个子类中只包含一个bass class对象。

  很多东西要有对比才能认识得更深刻,我们这里对比下虚拟继承和普通继承的子类对象的区别,也从而让我们更好地理解文章开头提到的书里的那句话。

  虚拟继承样例:

 

class CTestBase
{
   public:
      int base_data_;
};
 
class CTestSubject1:virtual class CTestBase
{
   public:
       int subone_data_;
};
 
class CTestSubject2:virtual class CTestBase
{
   public:
       int subtwo_data_;
};
 
 class CTestDiamond:public CTestSubject1,public CTestSubject2
{
   public:
       int dia_data_;
};

int main()
{
   CTestDiamond dia;
   dia.base_data_ = 1;
}

 

     上面当中dia.base_data_能够被赋值,再看普通继承的例子。

普通继承样例:

 1 class CTestBase
 2 {
 3    public:
 4      int base_data_;
 5 };
 6 
 7 class CTestSubject1:public CTestBase
 8 {
 9    public:
10      int subone_data_;
11 };
12 
13 class CTestSubject2:public CTestBase
14 {
15    public:
16      int subtwo_data_;
17 };
18 
19 class CTestDiamond:public CTestSubject1,public CTestSubject2
20 {
21    public:
22      int dia_data_;
23 }
24 
25 int main()
26 {
27    CTestDiamond dia;
28    dia.base_data_ =1;
29 }

     这时候就出问题了,同样的继承结构,但是只不过没有了虚拟继承,我们对dia.base_data_的赋值就不能通过编译了,这是因为没有了虚拟继承,我们的dia对象中有2个base_data_,一个是从CTestSubject1中继承来的,另一个是从CTestSubject2中继承来的。这样一来编译器就不知道具体要给哪个base_data_赋值了,而当我们用虚拟继承时,对象dia中只有一个base_data_,所以显而易见编译器就知道该怎么赋值。这就是那句话的意思,不管继承多少次,永远只会存在一个虚基类的实体。

     那我们该怎么在普通继承中对多个base_data_赋值呢?

     我们只需要dia.CTestSubject1::base_data_ = 1,这样编译器就知道我们是想给CTestSubject1中的base_data_赋值了。CTestSubject2里面的base_data_也同理。

     总结:

     通过上面的2个例子,我们很容易看出虚拟继承和普通继承的区别,我觉得学习语言不需要去纠结语法,而应该去理解各种语法用法之间的区别,具体怎么用,只有结合实际中的编程场景,通过分析选择最合适的方式来使用,相信存在即是道理。

     当然上面只是从表面来分析虚拟继承和普通继承,更深层次地可以从对象模型和内存布局去理解。