Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >从零开始学C++之继承(三):多重继承、虚继承与虚基类

从零开始学C++之继承(三):多重继承、虚继承与虚基类

作者头像
s1mba
发布于 2017-12-28 08:35:31
发布于 2017-12-28 08:35:31
1.2K00
代码可运行
举报
文章被收录于专栏:开发与安全开发与安全
运行总次数:0
代码可运行

一、多重继承

单重继承——一个派生类最多只能有一个基类 多重继承——一个派生类可以有多个基类

class 类名: 继承方式 基类1,继承方式 基类2,…. {….};

派生类同时继承多个基类的成员,更好的软件重用 可能会有大量的二义性,多个基类中可能包含同名变量或函数

多重继承中解决访问歧义的方法:

基类名::数据成员名(或成员函数(参数表)) 明确指明要访问定义于哪个基类中的成员

代码语言:cpp
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
using namespace std;

class Bed
{
public:
    Bed(int weight) : weight_(weight)
    {

    }
    void Sleep()
    {
        cout << "Sleep ..." << endl;
    }
    int weight_;
};

class Sofa
{
public:
    Sofa(int weight) : weight_(weight)
    {

    }
    void WatchTV()
    {
        cout << "Watch TV ..." << endl;
    }
    int weight_;
};

class SofaBed : public Bed, public Sofa
{
public:
    SofaBed() : Bed(0), Sofa(0)
    {
        FoldIn();
    }
    void FoldOut()
    {
        cout << "FoldOut ..." << endl;
    }
    void FoldIn()
    {
        cout << "FoldIn ..." << endl;
    }
};

int main(void)
{
    SofaBed sofaBed;
    //sofaBed.weight_ = 10; error
    //sofaBed.weight_ = 20; error

    sofaBed.Bed::weight_ = 10;
    sofaBed.Sofa::weight_ = 20;

    sofaBed.WatchTV();
    sofaBed.FoldOut();
    sofaBed.Sleep();

    return 0;
}

不能直接写 sofaBed.weight_ = 10; 因为sofaBed 继承了Sofa 和 Bed ,实际上有weigh_的两份拷贝,这样指向不明。只能通过

sofaBed.Bed::weight_ = 10; 访问,但实际上一个sofaBed理应只有一个weight_,下面通过虚基类和虚继承可以解决这个问题。

二、虚继承与虚基类

当派生类从多个基类派生,而这些基类又从同一个基类派生,则在访问此共同基类中的成员时,将产生二义性,可以采用虚基类来解决。

虚基类的引入 用于有共同基类的场合

声明 以virtual修饰说明基类 例:class B1:virtual public BB

作用

主要用来解决多继承时可能发生的对同一基类继承多次而产生的二义性问题. 为最远的派生类提供唯一的基类成员,而不重复产生多次拷贝

代码语言:cpp
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
using namespace std;

class Furniture
{
public:
    Furniture(int weight) : weight_(weight)
    {
        cout << "Furniture ..." << endl;
    }
    ~Furniture()
    {
        cout << "~Furniture ..." << endl;
    }
    int weight_;
};

class Bed : virtual public Furniture
{
public:
    Bed(int weight) : Furniture(weight)
    {
        cout << "Bed ..." << endl;
    }
    ~Bed()
    {
        cout << "~Bed ..." << endl;
    }
    void Sleep()
    {
        cout << "Sleep ..." << endl;
    }

};

class Sofa : virtual public Furniture
{
public:
    Sofa(int weight) : Furniture(weight)
    {
        cout << "Sofa ..." << endl;
    }
    ~Sofa()
    {
        cout << "~Sofa ..." << endl;
    }
    void WatchTV()
    {
        cout << "Watch TV ..." << endl;
    }
};

class SofaBed : public Bed, public Sofa
{
public:
    SofaBed(int weight) : Bed(weight), Sofa(weight), Furniture(weight)
    {
        cout << "SofaBed ..." << endl;
        FoldIn();
    }
    ~SofaBed()
    {
        cout << "~SofaBed ..." << endl;
    }
    void FoldOut()
    {
        cout << "FoldOut ..." << endl;
    }
    void FoldIn()
    {
        cout << "FoldIn ..." << endl;
    }
};

int main(void)
{
    SofaBed sofaBed(5);
    sofaBed.weight_ = 10;


    sofaBed.WatchTV();
    sofaBed.FoldOut();
    sofaBed.Sleep();

    return 0;
}

此时只有一份weigh_,不存在访问歧义的问题。

从输出可以总结出:

1、虚基类的成员是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的。 2、在整个继承结构中,直接或间接继承虚基类的所有派生类,都必须在构造函数的成员初始化表中给出对虚基类的构造函数的调用。如果未列出,则表示调用该虚基类的默认构造函数。 3、在建立对象时,只有最远派生类的构造函数调用虚基类的构造函数,该派生类的其他基类对虚基类构造函数的调用被忽略。

参考:

C++ primer 第四版 Effective C++ 3rd C++编程规范

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2013-07-12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
适合具备 C 语言基础的 C++ 入门教程(六)
再上一则教程中,着重讲述了派生类继承于父类之后的一些访问控制,在本次教程中,将介绍如下几个点:派生类扩展父类功能,派生类的空间分布,以及多重继承的相关概念。
wenzid
2021/02/20
2560
适合具备 C 语言基础的 C++ 入门教程(六)
c++头脑风暴-多态、虚继承、多重继承内存布局
gdb怎么用这里就不展开了,默认你会使用gdb,使用gdb设置打印格式,然后看对象people的内存布局及大小,如下:
cpp加油站
2021/06/29
7620
【C++高阶】C++继承学习手册:全面解析继承的各个方面
前言: 当我们踏上C++编程的旅程时,继承无疑是一个无法回避且至关重要的概念。作为面向对象编程的三大特性之一,继承不仅让我们能够创建出层次清晰、结构合理的代码,还极大地提高了代码的可重用性和可维护性。在本文中,我们将一起深入探讨C++继承的奥秘,从基础概念到高级应用,逐步揭开它的神秘面纱
Eternity._
2024/06/14
4920
【C++高阶】C++继承学习手册:全面解析继承的各个方面
【C++进阶学习】第三弹——菱形继承和虚拟继承——菱形继承的二义性和数据冗余问题
在这个例子中,Derived 类继承自 Base 类。Derived 类可以访问 Base 类中声明为 public 的成员。
GG Bond1
2024/06/22
5171
【C++进阶学习】第三弹——菱形继承和虚拟继承——菱形继承的二义性和数据冗余问题
【Example】C++ 虚基类与虚继承 (菱形继承问题)
C++ 是支持多继承的语言,但是实际项目开发中非必要请避免使用多继承以降低代码逻辑的复杂性。
芯片烤电池
2022/04/27
1.1K0
【C++】模板/继承/多态
基类对象 < -派生类对象 类型从下到上的转换(可以) 派生类对象 <- 基类对象 类型从上到下的转换(不可以) 基类指针(引用)<- 派生类对象 类型从下到上的转换(可以) 派生类指针(引用)<-基类对象 类型从上到下的转换(不可以)
洁洁
2024/09/05
1610
多继承三角和钻石问题(虚继承)
上一篇文章我们简单介绍了一下多继承的语法,但是我们遇到了一个问题,那就是如果多个父类具有相同名称的成员变量或成员方法,子类在调用的时候就会出现二义性问题,子类不知道选择哪一个父类的变量或方法,我们称之为三角问题。如下所示:
我与梦想有个约会
2023/10/20
1900
多继承三角和钻石问题(虚继承)
c++多重继承小结
如果一个类从两个不同的类里继承两个同名的成员,则需要在派生类中使用类限定符来区分他们。 即在从A和B派生出来的c类中使用a::Show()和B::Show()来区分从这两个类那里继承的show()方法 如果一个类通过多种途径继承了一个非虚基类,则该类从每种途径分别继承非虚基类的一个实例。多个基类 都是有问题的。使用虚基类的MI,当派生类使用关键字virtual来指示派生时,基类就成为虚基类: class A:public virtual B {} 主要变化是,从虚基类的一个或多个实例派生而来的类将只继承了一
lpxxn
2018/01/31
6880
【C++】继承
1. 继承是面向对象语言进行代码复用的一种手段,以前我们所接触的代码复用都是函数复用,譬如模拟实现vector的时候,尾插尾删都是复用了insert和erase接口。而继承提供的是一种类设计层次的代码复用,在原有类中增加扩展并实现新的功能,这样所产生的类叫做派生类或子类,原有类被称为基类或父类。
举杯邀明月
2023/04/12
7470
【C++】继承
C++继承(多继承、菱形继承?)
继承(inheritance)机制是面向对象程序设计,使代码可以复用的最重要的手段。它允许程序员在保持原有类特性的基础上进行扩展,以增加功能。这样产生新的类,称为派生类。
利刃大大
2023/04/12
2.1K0
C++继承(多继承、菱形继承?)
C++虚拟继承与虚基类
C++虚拟继承一般发生在多重继承的情况下。C++允许一个类有多个父类,这样就形成多重继承。多重继承使得派生类与基类的关系变得更为复杂,其中一个容易出现问题是某个基类沿着不同的路径被派生类继承(即形成所谓“菱形继承”),从而导致一个派生类对象中存在同一个基类对象的多个拷贝。
恋喵大鲤鱼
2018/08/03
9550
C++虚拟继承与虚基类
【C++】你不得不爱的——继承
 凡是面向对象的语言,都有三大特性,继承,封装和多态,但并不是只有这三个特性,是因为者三个特性是最重要的特性,那今天我们一起来看继承!
The sky
2023/04/12
4080
【C++】你不得不爱的——继承
c++那些事儿3.0 继承
一般形式 class class_name:继承方式 基类名{ code } 继承方式有三种: public ,protected,private. //java好像都是public继承。 单继承 多继承,多继承会很复杂,所以java,c sharp都采用interface。 类函数: 构造函数 先执行父类的构造函数,在执行子类的构造函数。 一般形式 派生类的构造函数(参数列表)
热心的社会主义接班人
2018/04/27
6010
c++那些事儿3.0 继承
【C++进阶篇】C++继承进阶:深入理解继承的复杂性
在 C++ 中,友元是一种特殊机制,它允许指定的非成员函数或者其他类访问类的私有成员和保护成员。然而,友元关系不能继承,也就是说,基类友元不能访问子类私有和保护成员,反之亦然。
熬夜学编程的小王
2024/12/24
1330
【C++进阶篇】C++继承进阶:深入理解继承的复杂性
菱形继承问题及解决方法—虚继承与虚基类(C++)
想要解决有两个思路,一是给羊驼的每一份数据加上作用域,但本质上羊驼还是继承了两份数据。二是通过虚继承的方式,使羊驼仅继承一份数据。
LonelyEnderman
2022/10/27
1.3K0
菱形继承问题及解决方法—虚继承与虚基类(C++)
继承
虚继承是为了解决棱形继承中成员访问的二义性。在A B继承方式前加关键字virtual,编译器将Base的数据保存在一个公共位置,通过虚基表访问。
DeROy
2020/06/03
7100
继承
C++:52---多重继承
一、多重继承概念 多重继承是指:从多个直接基类而产生派生类的能力 例如: class ZooAnimal {}; //动物 class Endangered {}; //濒临灭绝的动物 class B
用户3479834
2021/02/03
9950
C++:52---多重继承
【C++】继承
继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继承是类设计层次的复用。
zxctscl
2024/04/20
1470
【C++】继承
c++类和继承面试点25连问
c++的三大特性,说白了其实就是面向对象的三大特性,是指:封装、继承、多态,简单说明如下:
cpp加油站
2021/06/29
1K0
C++:继承
继承(inheritance)机制是面向对象程序设计使代码可以复用的重要手段,它允许程序员在保持着类特性的基础上进行扩展,增加功能,这样产生新的类,称为派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。之前用的比较多的是函数复用,继承是类设计层次的复用。
HZzzzzLu
2024/11/26
1020
C++:继承
相关推荐
适合具备 C 语言基础的 C++ 入门教程(六)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验