写点什么

C++ 的多重继承

作者:向阳逐梦
  • 2023-09-02
    四川
  • 本文字数:2318 字

    阅读完需:约 8 分钟

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() 函数。

发布于: 刚刚阅读数: 6
用户头像

向阳逐梦

关注

人生享受编程,编程造就人生! 2022-06-01 加入

某公司芯片测试工程师,嵌入式开发工程师,InfoQ签约作者,阿里云星级博主,华为云·云享专家。座右铭:向着太阳,追逐梦想!

评论

发布
暂无评论
C++的多重继承_向阳逐梦_InfoQ写作社区