第53课 被遗弃的多重继承

问题:
C++中是否允许一个类继承自多个父类呢?
答案是肯定的,这种现象就是多重继承
多重继承是C++中一个特有的特性,因为在其他的程序设计语言里面,如C#、java等语言只支持单重继承

C++支持编写多重继承的代码
-一个子类可以拥有多个父类
-子类拥有所有父类的成员变量
-子类继承所有父类的成员函数
-子类对象可以当作任意父类对象使用

多重继承的语法规则

class Derived: public BaseA,
               public BaseB,
               public BaseC
{
    // ....
};

多重继承的本质与单继承相同

#include <iostream>
#include <string>

using namespace std;

class BaseA
{
    int ma;
public:
    BaseA(int a)
    {
        ma = a;
    }
    int getA()
    {
        return ma;
    }
};

class BaseB
{
    int mb;
public:
    BaseB(int b)
    {
        mb = b;
    }
    int getB()
    {
        return mb;
    }
};

class Derived : public BaseA, public BaseB
{
    int mc;
public:
    Derived(int a, int b, int c) : BaseA(a), BaseB(b)
    {
        mc = c;
    }
    int getC()
    {
        return mc;
    }
    void print()
    {
        cout << "ma = " << getA() << ", "
             << "mb = " << getB() << ", "
             << "mc = " << mc << endl;
    }
};

int main()
{
    cout << "sizeof(Derived) = " << sizeof(Derived) << endl;    // 12

    Derived d(1, 2, 3);

    d.print();

    cout << "d.getA() = " << d.getA() << endl;
    cout << "d.getB() = " << d.getB() << endl;
    cout << "d.getC() = " << d.getC() << endl;

    cout << endl;

    BaseA* pa = &d;
    BaseB* pb = &d;

    cout << "pa->getA() = " << pa->getA() << endl;
    cout << "pb->getB() = " << pb->getB() << endl;

    cout << endl;

    void* paa = pa;
    void* pbb = pb;

    if( paa == pbb )
    {
        cout << "Pointer to the same object!" << endl;
    }
    else
    {
        cout << "Error" << endl;
    }

    cout << "pa = " << pa << endl;
    cout << "pb = " << pb << endl;
    cout << "paa = " << paa << endl;
    cout << "pbb = " << pbb << endl;

    return 0;
}

上面的程序,反映了多重继承的问题:
通过多重继承得到的对象可能拥有不同的地址
解决方案:无

pa和pb还是指向了同一个对象,但是指向的是同一个对象的不同位置。
两个指针的地址值不同,它们依然可以指向同一个对象

多重继承的问题二:
多重继承可能产生冗余的成员

这样发生多重继承后,Doctor中有两个m_name,两个m_age.从现实的角度来看,这是有问题的。

C++提出了一种比较有效的解决方法,

当多重继承关系出现闭合时将产生数据冗余的问题
解决方案:虚继承

class People {};
class Teacher : virtual public People {};
class Student : virtual public People {};
class Doctor : public Teacher, public Student
{
};
#include <iostream>
#include <string>

using namespace std;

class People
{
    string m_name;
    int m_age;
public:
    People(string name, int age)
    {
        m_name = name;
        m_age = age;
    }
    void print()
    {
        cout << "Name = " << m_name << ", "
             << "Age = " << m_age << endl;
    }
};

class Teacher : virtual public People
{
public:
    Teacher(string name, int age) : People(name, age)
    {
    }
};

class Student : virtual public People
{
public:
    Student(string name, int age) : People(name, age)
    {
    }
};

class Doctor : public Teacher, public Student
{
public:
    Doctor(string name, int age) : Teacher(name, age), Student(name, age), People(name, age)
    {
    }
};

int main()
{
    Doctor d("Goertek", 33);

    d.print();

    return 0;
}

虚继承能够解决数据冗余问题
中间层父类不再关心顶层父类的初始化
最终子类必须直接调用顶层父类的构造函数

虚继承在技术方面确实解决了数据冗余问题,但是它使程序变得过于复杂,不利于工程方面的应用。

如果在项目中引进多重继承,当架构设计中需要继承时,无法确定使用直接继承还是虚继承。

注意:多继承只适合做学术研究,不适合做工程开发

小结:
C++支持多重继承的编程方式
多重继承容易带来问题
-可能出现同一个对象的地址不同的情况 。
-虚继承可以解决数据冗余问题
-虚继承使得架构设计可能出现问题

原文地址:https://www.cnblogs.com/-glb/p/11967916.html

时间: 2024-10-10 20:43:11

第53课 被遗弃的多重继承的相关文章

第53课 被遗弃的多重继承(上)

1. 单一继承 (1)实验代码 #include <iostream> #include <string> using namespace std; void visitVtbl(int **vtbl) { cout << vtbl << endl; cout << "\t[-1]: " << (long)vtbl[-1] << endl; typedef void (*FuncPtr)(); int

第53课 被遗弃的多重继承 (中)

多重继承的问题三:多重继承可能产生多个虚函数表 #include <iostream> using namespace std; class BaseA { public: virtual void funcA() { cout << "BaseA::funcA()" << endl; } }; class BaseB { public: virtual void funcB() { cout << "BaseB::funcB(

第53课 被遗弃的多重继承 (下)——正确的使用多重继承

工程开发中的多重继承方式:(这是面向对象理论中所推荐的方式)单继承某个类 + 实现(多个)接口 #include <iostream> #include <string> using namespace std; class Base { protected: int mi; public: Base(int i) { mi = i; } int getI() { return mi; } bool equal(Base* obj) { return (this == obj);

第54课 被遗弃的多重继承(下)

1. C++中的多重继承 (1)一个子类可以拥有多个父类 (2)子类拥有所有父类的成员变量 (3)子类继承所有父类的成员函数 (4)子类对象可以当作任意父类对象使用 (5)多重继承的语法规则 class Derived: public BaseA, public BaseB, public BaseC{…}; 2. 多重继承问题一 (1)通过多重继承得到的对象可以拥有“不同的地址”!!! (2)解释方案:无 (3)原因分析 [编程实验]多重继承问题一 #include <iostream> u

C++--被遗弃的多重继承、经典问题

一.被遗弃的多重继承 Q:C++中是否允许一个类继承自多个父类?在实际的C++编译环境中,C++是支持编写多重继承的代码1.一个子类可以拥有多个父类2.子类拥有所有父类的成员变量3.子类继承所有父类的成员函数4.子类对象可以当作任意父类对象使用多重继承的语法规则但是在多重继承中会存在许多问题Q:多重继承得到的对象可能拥有不同的地址代码示例 #include <iostream> #include <string> using namespace std; class BaseA {

第五十三课、被遗弃的多重继承(上)

一.c++的多重继承 1.c++支持编写多重继承的代码 (1).一个子类可以拥有多个父类 (2).子类拥有所有父类的成员变量 (3).子类继承所有父类的成员函数 (4).子类对象可以当做任意父类对象使用 2.多重继承产生的问题一:通过多重继承得到的对象拥有不同的地址 #include<iostream> using namespace std; class BaseA { protected: int ma; public: BaseA(int a) { ma = a; } int GetA(

第53课:Hive 第一课:Hive的价值、Hive的架构设计简介

一. Hive的历史价值 1, 大数据因Hadoop而知名,而Hadoop又因Hive而实用.Hive是Hadoop上的Killer Application,Hive是Hadoop上的数据仓库,同时Hive兼具有数据仓库中的存储和查询引擎.而Spark SQL是一个更加出色和高级的查询引擎,并不提供存储功能.所以Spark SQL无法取代Hive,在现在企业级应用中Spark SQL+Hive成为了业界使用的大数据最为高效和流行的趋势. 2,Hive是Facebook推出的,主要是为了让不懂ja

小学生趣味C++编程第53课 化功大法(完整)

链接:https://pan.baidu.com/s/1qDdBkFPakLtCvh8_W2wiog 提取码:x3zg #include<iostream> #include<cmath> //调用求浮点数的绝对值函数fabs() using namespace std; int main() { double x,y; long long a,b,i,j; cout<<"请输入一个纯小数"<<endl; do { cout<<

第0课 - 数据结构引言

第0课 - 课程目标(实现一个轻量级STL) 第1课 - 进阶高手的大门 第2课 - 数据的艺术 第3课 - 初识程序的灵魂 第4课 - 程序灵魂的审判 第5课 - 算法的时间复杂度 第6课 - 算法效率的度量 第7课 - 课程学习小问答 第8课 - 泛型编程简介 第9课 - 智能指针示例 第10课 - C++异常简介 第11课 - 异常类构建 第12课 - 顶层父类的创建 第13课 - 类族结构的进化 第14课 - 线性表的本质和操作 第15课 - 线性表的顺序存储结构 第16课 - 顺序存储