C++虚拟继承解决菱形继承的二义性

2024-01-05 19:18

本文主要是介绍C++虚拟继承解决菱形继承的二义性,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在过去的学习中,我们始终接触的单个类的继承,但是在现实生活中,一些新事物往往会拥有两个或者两个以上事物的属性,为了解决这个问题,C++引入了多重继承的概念, C++允许为一个派生类指定多个基类,这样的继承结构被称做多重继承

  举个例子,交通工具类可以派生出汽车和船连个子类,但拥有汽车和船共同特性水陆两用汽车就必须继承来自汽车类与船类的共同属性。

  由此我们不难想出如下的图例与代码:

  当一个派生类要使用多重继承的时候,必须在派生类名和冒号之后列出所有基类的类名,并用逗好分隔。

//程序作者:管宁   
//站点:www.cndev-lab.com   
//所有稿件均有版权,如要转载,请务必著名出处和作者   
 
#include <iostream
using namespace std; 
 
class Vehicle 

    public
        Vehicle(int weight = 0) 
        { 
            Vehicle::weight = weight; 
        } 
        void SetWeight(int weight) 
        { 
            cout<<"重新设置重量"<<endl; 
            Vehicle::weight = weight; 
        } 
        virtual void ShowMe() = 0; 
    protected
        int weight; 
}; 
class Car:public Vehicle//汽车 

    public
        Car(int weight=0,int aird=0):Vehicle(weight) 
        { 
            Car::aird = aird; 
        } 
        void ShowMe() 
        { 
            cout<<"我是汽车!"<<endl; 
        } 
    protected
        int aird; 
}; 
 
class Boat:public Vehicle//船 

    public
        Boat(int weight=0,float tonnage=0):Vehicle(weight) 
        { 
            Boat::tonnage = tonnage; 
        } 
        void ShowMe() 
        { 
            cout<<"我是船!"<<endl; 
        } 
    protected
        float tonnage; 
}; 
 
class AmphibianCar:public Car,public Boat//水陆两用汽车,多重继承的体现 

    public
        AmphibianCar(int weight,int aird,float tonnage) 
        :Vehicle(weight),Car(weight,aird),Boat(weight,tonnage) 
        //多重继承要注意调用基类构造函数 
        { 
         
        } 
        void ShowMe() 
        { 
            cout<<"我是水陆两用汽车!"<<endl; 
        } 
}; 
int main() 

    AmphibianCar a(4,200,1.35f);//错误 
    a.SetWeight(3);//错误 
    system("pause");  
}

  上面的代码从表面看,看不出有明显的语发错误,但是它是不能够通过编译的。这有是为什么呢?
  这是由于多重继承带来的继承的模糊性带来的问题。

2 回顶部


  先看如下的图示:

  在图中深红色标记出来的地方正是主要问题所在,水陆两用汽车类继承了来自Car类与Boat类的属性与方法,Car类与Boat类同为AmphibianCar类的基类,在内存分配上AmphibianCar获得了来自两个类的SetWeight()成员函数,当我们调用a.SetWeight(3)的时候计算机不知道如何选择分别属于两个基类的被重复拥有了的类成员函数SetWeight()。

  由于这种模糊问题的存在同样也导致了AmphibianCar a(4,200,1.35f);执行失败,系统会产生Vehicle”不是基或成员的错误。

  以上面的代码为例,我们要想让AmphibianCar类既获得一个Vehicle的拷贝,而且又同时共享用Car类与Boat类的数据成员与成员函数就必须通过C++所提供的虚拟继承技术来实现。

  我们在Car类和Boat类继承Vehicle类出,在前面加上virtual关键字就可以实现虚拟继承,使用虚拟继承后,当系统碰到多重继承的时候就会自动先加入一个Vehicle的拷贝,当再次请求一个Vehicle的拷贝的时候就会被忽略,保证继承类成员函数的唯一性

  修改后的代码如下,注意观察变化:

//程序作者:管宁   
//站点:www.cndev-lab.com   
//所有稿件均有版权,如要转载,请务必著名出处和作者   
 
#include <iostream
using namespace std; 
 
class Vehicle 

    public
        Vehicle(int weight = 0) 
        { 
            Vehicle::weight = weight; 
            cout<<"载入Vehicle类构造函数"<<endl; 
        } 
        void SetWeight(int weight) 
        { 
            cout<<"重新设置重量"<<endl; 
            Vehicle::weight = weight; 
        } 
        virtual void ShowMe() = 0; 
    protected
        int weight; 
}; 
class Car:virtual public Vehicle//汽车,这里是虚拟继承 

    public
        Car(int weight=0,int aird=0):Vehicle(weight) 
        { 
            Car::aird = aird; 
            cout<<"载入Car类构造函数"<<endl; 
        } 
        void ShowMe() 
        { 
            cout<<"我是汽车!"<<endl; 
        } 
    protected
        int aird; 
}; 
 
class Boat:virtual public Vehicle//船,这里是虚拟继承 

    public
        Boat(int weight=0,float tonnage=0):Vehicle(weight) 
        { 
            Boat::tonnage = tonnage; 
            cout<<"载入Boat类构造函数"<<endl; 
        } 
        void ShowMe() 
        { 
            cout<<"我是船!"<<endl; 
        } 
    protected
        float tonnage; 
}; 
 
class AmphibianCar:public Car,public Boat//水陆两用汽车,多重继承的体现 

    public
        AmphibianCar(int weight,int aird,float tonnage) 
        :Vehicle(weight),Car(weight,aird),Boat(weight,tonnage) 
        //多重继承要注意调用基类构造函数 
        { 
            cout<<"载入AmphibianCar类构造函数"<<endl; 
        } 
        void ShowMe() 
        { 
            cout<<"我是水陆两用汽车!"<<endl; 
        } 
        void ShowMembers() 
        { 
            cout<<"重量:"<<weight<<"顿,"<<"空气排量:"<<aird<<"CC,"<<"排水量:"<<tonnage<<"顿"<<endl; 
        } 
}; 
int main() 

    AmphibianCar a(4,200,1.35f); 
    a.ShowMe(); 
    a.ShowMembers(); 
    a.SetWeight(3); 
    a.ShowMembers(); 
    system("pause");  
}

  注意观察类构造函数的构造顺序。

  虽然说虚拟继承与虚函数有一定相似的地方,但读者务必要记住,他们之间是绝对没有任何联系的!

这篇关于C++虚拟继承解决菱形继承的二义性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/573895

相关文章

C++中NULL与nullptr的区别小结

《C++中NULL与nullptr的区别小结》本文介绍了C++编程中NULL与nullptr的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编... 目录C++98空值——NULLC++11空值——nullptr区别对比示例 C++98空值——NUL

C++ Log4cpp跨平台日志库的使用小结

《C++Log4cpp跨平台日志库的使用小结》Log4cpp是c++类库,本文详细介绍了C++日志库log4cpp的使用方法,及设置日志输出格式和优先级,具有一定的参考价值,感兴趣的可以了解一下... 目录一、介绍1. log4cpp的日志方式2.设置日志输出的格式3. 设置日志的输出优先级二、Window

SQL Server配置管理器无法打开的四种解决方法

《SQLServer配置管理器无法打开的四种解决方法》本文总结了SQLServer配置管理器无法打开的四种解决方法,文中通过图文示例介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录方法一:桌面图标进入方法二:运行窗口进入检查版本号对照表php方法三:查找文件路径方法四:检查 S

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

Redis出现中文乱码的问题及解决

《Redis出现中文乱码的问题及解决》:本文主要介绍Redis出现中文乱码的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 问题的产生2China编程. 问题的解决redihttp://www.chinasem.cns数据进制问题的解决中文乱码问题解决总结

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

c++中的set容器介绍及操作大全

《c++中的set容器介绍及操作大全》:本文主要介绍c++中的set容器介绍及操作大全,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录​​一、核心特性​​️ ​​二、基本操作​​​​1. 初始化与赋值​​​​2. 增删查操作​​​​3. 遍历方

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

C++11委托构造函数和继承构造函数的实现

《C++11委托构造函数和继承构造函数的实现》C++引入了委托构造函数和继承构造函数这两个重要的特性,本文主要介绍了C++11委托构造函数和继承构造函数的实现,具有一定的参考价值,感兴趣的可以了解一下... 目录引言一、委托构造函数1.1 委托构造函数的定义与作用1.2 委托构造函数的语法1.3 委托构造函