仪陇家园分类信息网、仪陇生活网、仪陇家园网

搜索

多重继承之虚继承(主要是为了解决产生的数据冗余问题)

[复制链接]
seo 发表于 2022-5-31 13:29:16 | 显示全部楼层 |阅读模式
多重继承之虚继承(主要是为了解决产生的数据冗余问题)发布时间:2022/5/31 13:16:23
            
                                                       
                                                       
            
        
        
               
                     
虚继承 是面向对象编程中的一种技术,是指一个指定的基类,在继承体系结构中,将其成员数据实例共享给也从这个基类型直接或间接派生的其它类。形式:
在继承定义中包含了virtual关键字的继承关系,如下图中,类A就叫做虚基类。

  虚拟继承是多重继承中的菱形继承所特有的概念。虚拟基类是为解决多重继承而出现的。







  菱形继承中既有多继承,如下图所示:







  菱形继承中也有多重继承:







现实中的例子:









问题来了:在类D的实例中将有两份类A的变量,这种数据冗余的现象我们不能容忍其存在?这就会需要用到虚继承!!!废话不多说直接上代码,直接粘贴可用。

#include

#include
#include
using namespace std;


/**
  * 定义人类: Person
  */
class Person
{
public:
     Person(string color = "blue"):m_strColor(color)
{
cout }
~Person()
{
cout }
void eat()
{
         cout cout }
protected:
     string m_strColor;
};


/**
  * 定义工人类: Worker
  * 虚继承人类
  */
class Worker :  virtual public Person
{
public:
Worker(string name,string color):Person("Worker"+color)
{
m_strName = name;
cout }
~Worker()
{
cout }
void work()
{
cout cout }
protected:
string m_strName;
};


/**
  * 定义儿童类:Children
  * 虚继承人类
  */
class Children : virtual public Person
{
public:
Children(int age,string color):Person("Children"+ color)
{
m_iAge = age;
cout }
~Children()
{
cout }
void play()
{
         coutcout cout }
protected:
int m_iAge;
};


/**
  * 定义童工类:ChildLabourer
  * 公有继承工人类和儿童类
  */
class ChildLabourer:public Children,public Worker
{
public:
ChildLabourer(string name, int age,string color):Worker(name,color),Children(age,color)
{
cout }


~ChildLabourer()
{
cout }
};


int main(void)
{
     // 用new关键字实例化童工类对象
ChildLabourer * p = new ChildLabourer("qq",14,"yellow");
     // 调用童工类对象各方法。
//   p->eat();
         p->Worker::eat();
         p->Children::eat();
p->work();
p->play();
delete p;
p = NULL;


return 0;


}

输出:



Person
Children
Worker
ChildLabourer
blue
Person -- eat
blue
Person -- eat
qq
work
0x60314814
play
~ChildLabourer
~Worker
~Children
~Person
如果不加virtual关键字时候的输出:




Person
Children
Person
Worker
ChildLabourer
Workeryellow
Person -- eat
Childrenyellow
Person -- eat
qq
work
0x60310814
play
~ChildLabourer
~Worker
~Person
~Children
~Person
分析:


(1)不加virtual情况:

不加virtual,也就是不是虚继承的情况下,在实例化童工这个类的时候,会按继承顺序,先调用类Children的构造函数再调用类Worker的构造函数,最后调用自己的构造函数,而调用Children和Worker的构造函数的时候又会分别先调用它们的基类Person的构造函数,这样就会生成两个Person的对象,从而生成两份Person所含有的数据成员,即童工类ChildLabourer在实例化的时会生成在内存中会生成两份Person的数据成员,所以在调用Children和Worker的eat()函数的时候,会分别打印出Workeryellow和Childrenyellow,(这里注意Children和Worker里面的eat()都是从Person继承来的,因此分别都会打印出Person --eat;还要注意调用方式:p->Worker::eat();p->Children::eat())


销毁对象时,会先调用自己的析构函数,再调用两个基类的析构函数,两个基类的析构函数调用之前都会先调用Person的析构函数。调用析构函数的顺序和调用构造函数相反。

(2)加virtual的情况:

加virtual以后,从输出结果可以看出,在实例化童工类ChildrenLabourer时,构造函数的调用顺序比较正常,只调用了一次Person,析构函数的调用也只会调用一次Person的析构函数,这说明实例化童工类时只会生成一份Person的对象,表明了在对象的内存空间中仅仅能够包含一份虚基类的对象,而且打印的结果都是blue,即ChildrenLabourer的数据不会再传入虚基类Person。这就讲数据冗余的问题解决了。
               
        
        
   
            
        
        
回复

使用道具 举报

全部回复0 显示全部楼层

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

楼主

审核员

热门推荐

联系客服 关注微信 下载APP 返回顶部 返回列表