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++ move 的作用详解及陷阱最佳实践

《C++move的作用详解及陷阱最佳实践》文章详细介绍了C++中的`std::move`函数的作用,包括为什么需要它、它的本质、典型使用场景、以及一些常见陷阱和最佳实践,感兴趣的朋友跟随小编一起看... 目录C++ move 的作用详解一、一句话总结二、为什么需要 move?C++98/03 的痛点⚡C++

详解C++ 存储二进制数据容器的几种方法

《详解C++存储二进制数据容器的几种方法》本文主要介绍了详解C++存储二进制数据容器,包括std::vector、std::array、std::string、std::bitset和std::ve... 目录1.std::vector<uint8_t>(最常用)特点:适用场景:示例:2.std::arra

C++构造函数中explicit详解

《C++构造函数中explicit详解》explicit关键字用于修饰单参数构造函数或可以看作单参数的构造函数,阻止编译器进行隐式类型转换或拷贝初始化,本文就来介绍explicit的使用,感兴趣的可以... 目录1. 什么是explicit2. 隐式转换的问题3.explicit的使用示例基本用法多参数构造

解决idea启动项目报错java: OutOfMemoryError: insufficient memory

《解决idea启动项目报错java:OutOfMemoryError:insufficientmemory》:本文主要介绍解决idea启动项目报错java:OutOfMemoryError... 目录原因:解决:总结 原因:在Java中遇到OutOfMemoryError: insufficient me

maven异常Invalid bound statement(not found)的问题解决

《maven异常Invalidboundstatement(notfound)的问题解决》本文详细介绍了Maven项目中常见的Invalidboundstatement异常及其解决方案,文中通过... 目录Maven异常:Invalid bound statement (not found) 详解问题描述可

C++,C#,Rust,Go,Java,Python,JavaScript的性能对比全面讲解

《C++,C#,Rust,Go,Java,Python,JavaScript的性能对比全面讲解》:本文主要介绍C++,C#,Rust,Go,Java,Python,JavaScript性能对比全面... 目录编程语言性能对比、核心优势与最佳使用场景性能对比表格C++C#RustGoJavapythonjav

C++打印 vector的几种方法小结

《C++打印vector的几种方法小结》本文介绍了C++中遍历vector的几种方法,包括使用迭代器、auto关键字、typedef、计数器以及C++11引入的范围基础循环,具有一定的参考价值,感兴... 目录1. 使用迭代器2. 使用 auto (C++11) / typedef / type alias

C++ scoped_ptr 和 unique_ptr对比分析

《C++scoped_ptr和unique_ptr对比分析》本文介绍了C++中的`scoped_ptr`和`unique_ptr`,详细比较了它们的特性、使用场景以及现代C++推荐的使用`uni... 目录1. scoped_ptr基本特性主要特点2. unique_ptr基本用法3. 主要区别对比4. u

C++11中的包装器实战案例

《C++11中的包装器实战案例》本文给大家介绍C++11中的包装器实战案例,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录引言1.std::function1.1.什么是std::function1.2.核心用法1.2.1.包装普通函数1.2.

C++多线程开发环境配置方法

《C++多线程开发环境配置方法》文章详细介绍了如何在Windows上安装MinGW-w64和VSCode,并配置环境变量和编译任务,使用VSCode创建一个C++多线程测试项目,并通过配置tasks.... 目录下载安装 MinGW-w64下载安装VS code创建测试项目配置编译任务创建 tasks.js