C++多继承(多重继承)的实现

 更新时间:2023年04月18日 10:24:17   作者:C语言中文网  
多继承容易让代码逻辑复杂、思路混乱,本文主要介绍了C++多继承(多重继承)的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在前面的例子中,派生类都只有一个基类,称为单继承(Single Inheritance)。除此之外,C++也支持多继承(Multiple Inheritance),即一个派生类可以有两个或多个基类。

多继承容易让代码逻辑复杂、思路混乱,一直备受争议,中小型项目中较少使用,后来的 Java、C#、PHP 等干脆取消了多继承。

多继承的语法也很简单,将多个基类用逗号隔开即可。例如已声明了类A、类B和类C,那么可以这样来声明派生类D:

class D: public A, private B, protected C{
    //类D新增加的成员
}

D 是多继承形式的派生类,它以公有的方式继承 A 类,以私有的方式继承 B 类,以保护的方式继承 C 类。D 根据不同的继承方式获取 A、B、C 中的成员,确定它们在派生类中的访问权限。

多继承下的构造函数

多继承形式下的构造函数和单继承形式基本相同,只是要在派生类的构造函数中调用多个基类的构造函数。以上面的 A、B、C、D 类为例,D 类构造函数的写法为:

D(形参列表): A(实参列表), B(实参列表), C(实参列表){
    //其他操作
}

基类构造函数的调用顺序和和它们在派生类构造函数中出现的顺序无关,而是和声明派生类时基类出现的顺序相同。仍然以上面的 A、B、C、D 类为例,即使将 D 类构造函数写作下面的形式:

D(形参列表): B(实参列表), C(实参列表), A(实参列表){
    //其他操作
}

那么也是先调用 A 类的构造函数,再调用 B 类构造函数,最后调用 C 类构造函数。

下面是一个多继承的实例:

#include <iostream>
using namespace std;
//基类
class BaseA{
public:
    BaseA(int a, int b);
    ~BaseA();
protected:
    int m_a;
    int m_b;
};
BaseA::BaseA(int a, int b): m_a(a), m_b(b){
    cout<<"BaseA constructor"<<endl;
}
BaseA::~BaseA(){
    cout<<"BaseA destructor"<<endl;
}
//基类
class BaseB{
public:
    BaseB(int c, int d);
    ~BaseB();
protected:
    int m_c;
    int m_d;
};
BaseB::BaseB(int c, int d): m_c(c), m_d(d){
    cout<<"BaseB constructor"<<endl;
}
BaseB::~BaseB(){
    cout<<"BaseB destructor"<<endl;
}
//派生类
class Derived: public BaseA, public BaseB{
public:
    Derived(int a, int b, int c, int d, int e);
    ~Derived();
public:
    void show();
private:
    int m_e;
};
Derived::Derived(int a, int b, int c, int d, int e): BaseA(a, b), BaseB(c, d), m_e(e){
    cout<<"Derived constructor"<<endl;
}
Derived::~Derived(){
    cout<<"Derived destructor"<<endl;
}
void Derived::show(){
    cout<<m_a<<", "<<m_b<<", "<<m_c<<", "<<m_d<<", "<<m_e<<endl;
}
int main(){
    Derived obj(1, 2, 3, 4, 5);
    obj.show();
    return 0;
}

运行结果:

BaseA constructor
BaseB constructor
Derived constructor
1, 2, 3, 4, 5
Derived destructor
BaseB destructor
BaseA destructor

从运行结果中还可以发现,多继承形式下析构函数的执行顺序和构造函数的执行顺序相反。

命名冲突

当两个或多个基类中有同名的成员时,如果直接访问该成员,就会产生命名冲突,编译器不知道使用哪个基类的成员。这个时候需要在成员名字前面加上类名和域解析符::,以显式地指明到底使用哪个类的成员,消除二义性。

修改上面的代码,为 BaseA 和 BaseB 类添加 show() 函数,并将 Derived 类的 show() 函数更名为 display():

#include <iostream>
using namespace std;
//基类
class BaseA{
public:
    BaseA(int a, int b);
    ~BaseA();
public:
    void show();
protected:
    int m_a;
    int m_b;
};
BaseA::BaseA(int a, int b): m_a(a), m_b(b){
    cout<<"BaseA constructor"<<endl;
}
BaseA::~BaseA(){
    cout<<"BaseA destructor"<<endl;
}
void BaseA::show(){
    cout<<"m_a = "<<m_a<<endl;
    cout<<"m_b = "<<m_b<<endl;
}
//基类
class BaseB{
public:
    BaseB(int c, int d);
    ~BaseB();
    void show();
protected:
    int m_c;
    int m_d;
};
BaseB::BaseB(int c, int d): m_c(c), m_d(d){
    cout<<"BaseB constructor"<<endl;
}
BaseB::~BaseB(){
    cout<<"BaseB destructor"<<endl;
}
void BaseB::show(){
    cout<<"m_c = "<<m_c<<endl;
    cout<<"m_d = "<<m_d<<endl;
}
//派生类
class Derived: public BaseA, public BaseB{
public:
    Derived(int a, int b, int c, int d, int e);
    ~Derived();
public:
    void display();
private:
    int m_e;
};
Derived::Derived(int a, int b, int c, int d, int e): BaseA(a, b), BaseB(c, d), m_e(e){
    cout<<"Derived constructor"<<endl;
}
Derived::~Derived(){
    cout<<"Derived destructor"<<endl;
}
void Derived::display(){
    BaseA::show();  //调用BaseA类的show()函数
    BaseB::show();  //调用BaseB类的show()函数
    cout<<"m_e = "<<m_e<<endl;
}
int main(){
    Derived obj(1, 2, 3, 4, 5);
    obj.display();
    return 0;
}

请读者注意第 64、65 行代码,我们显式的指明了要调用哪个基类的 show() 函数。

到此这篇关于C++多继承(多重继承)的实现的文章就介绍到这了,更多相关C++多继承内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 利用Qt实现获取计算机的硬件信息

    利用Qt实现获取计算机的硬件信息

    在开发时,常常会需要用到计算机的相关信息。利用这些信息,我们可以开发一些辅助模块。本文将利用Qt实现获取计算机的硬件信息,感兴趣的可以尝试一下
    2022-12-12
  • C++实现高校人员信息管理系统

    C++实现高校人员信息管理系统

    这篇文章主要为大家详细介绍了C++实现高校人员信息管理系统项,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • 求32位机器上unsigned int的最大值及int的最大值的解决方法

    求32位机器上unsigned int的最大值及int的最大值的解决方法

    本篇文章是对求32位机器上unsigned int的最大值及int的最大值的解决方法进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • 详解C语言中的Static关键字

    详解C语言中的Static关键字

    这篇文章主要为大家介绍了C语言中Static关键字,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-01-01
  • C语言文件操作函数freopen详细解析

    C语言文件操作函数freopen详细解析

    替换一个流,或者说重新分配文件指针,实现重定向。如果stream流已经打开,则先关闭该流。如果该流已经定向,则freopen将会清除该定向。此函数一般用于将一个指定的文件打开一个预定义的流:标准输入、标准输出或者标准出错
    2013-10-10
  • 一文教你快速了解C语言中的作用域和常量

    一文教你快速了解C语言中的作用域和常量

    作用域(scope)是程序设计概念,通常来说一段程序代码中所用到的名字并不总是有效/可用,下面这篇文章主要给大家介绍了关于如何快速了解C语言中的作用域和常量的相关资料,需要的朋友可以参考下
    2023-06-06
  • C++实现遗传算法

    C++实现遗传算法

    这篇文章主要介绍了C++实现遗传算法,以实例形式较为详细的分析了遗传算法的C++实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-12-12
  • C++设计模式之观察者模式

    C++设计模式之观察者模式

    这篇文章主要介绍了C++设计模式之观察者模式,本文讲解了什么是观察者模式、观察者模式的UML类图、观察者模式的使用场合等内容,需要的朋友可以参考下
    2014-10-10
  • 获取C++变量类型的简单方法

    获取C++变量类型的简单方法

    这篇文章主要介绍了获取C++变量类型的简单方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • C++简明图解this指针的使用

    C++简明图解this指针的使用

    this 指针在C++类和对象中是个很方便实用的关键字,可以简化对象成员属性的调用,使代码表达的含义更加准确;在之前的学习中我们都可以判断变量所占内存空间大小,那么我们创建的类对象所占的内存空间怎么计算呢?想知道this的妙用和类对象占用的内存空间就来跟我学习吧
    2022-06-06

最新评论