使用虚拟继承解决菱形继承的问题

虚拟继承

菱形继承:两个子类继承同一个父类,而又有子类同时继承这两个子类
如果父类中可被子类访问的数据成员或函数成员被子类一路继承下去,那么子类中使用时会出现调用不明确

#include <iostream>

/* 一个类有两个父类,这两个父类又都继承自同一个父类,就形成了菱形继承 */

class Base {
public:
    /*virtual*/ void f() {
        std::cout << "f() in Base" << std::endl;
        h();
    }
protected:
    void g() {
        std::cout << "g() in Base" << std::endl;
    }
private:
    void h() {
        std::cout << "h() in Base" << std::endl;
    }
};

class Derived1Level1 : public virtual Base {
public:
    /* 这里如果加上关键字override是错误的,会提示不能重写基类成员,
       原因是virtual继承和virtual function是两个概念,virtual继承并不是让每个成员都变成了虚函数
       如果在virtual继承中使用虚函数那么要在函数原型中加上virtual关键字 */
    void f() /*override*/{
        std::cout << "f() in Derived1Level1" << std::endl;
        g();
        h();
    }
    void h() {
        std::cout << "h() in Derived1Level1" << std::endl;
    }
};

class Derived2Level1 : public virtual Base {
public:
    void f() {
        std::cout << "f() in Derived2Level1" << std::endl;
        g();
        // h();  // error: Base::h() is not accessible
    }
};

class DerivedLevel2 : public Derived1Level1, public Derived2Level1 {
public:
    void f() {
        std::cout << "f() in Derived1Level2" << std::endl;

        g(); // 如果Derived1Level1和Derived2Level1继承Base时不加virtual此处会提示对g的调用不明确,
             // 因此虚拟继承主要是为了解决此类菱形继承的问题
        Derived1Level1::h();
    }
};

int main()
{
    DerivedLevel2 dl2;
    dl2.f();

    return 0;
}

菱形继承示例

Base
+f()
#g()
-h()
Derived1Level1
+f()
+g()
Derived2Level1
+f()
DerivedLevel2
+f()

虚函数

#include <iostream>

/* 一个类有两个父类,这两个父类又都继承自同一个父类,就形成了菱形继承 */

class Base {
public:
    virtual void f() {
        std::cout << "f() in Base" << std::endl;
        h();
    }
    virtual void foo() {
        std::cout << "foo() in Base" << std::endl;
    }
    virtual void bar() {
        std::cout << "bar() in Base" << std::endl;
    }
protected:
    void g() {
        std::cout << "g() in Base" << std::endl;
    }
private:
    void h() {
        std::cout << "h() in Base" << std::endl;
    }
};

class Derived1Level1 : public virtual Base {
public:
    /* 这里如果加上关键字override是错误的,会提示不能重写基类成员,
       原因是virtual继承和virtual function是两个概念,virtual继承并不是让每个成员都变成了虚函数
       如果在virtual继承中使用虚函数那么要在函数原型中加上virtual关键字 */
    void f() /*override*/{
        std::cout << "f() in Derived1Level1" << std::endl;
        g();
        h();
    }
    void h() {
        std::cout << "h() in Derived1Level1" << std::endl;
    }
};

class Derived2Level1 : public virtual Base {
public:
    void f() {
        std::cout << "f() in Derived2Level1" << std::endl;
        g();
        // h();  // error: Base::h() is not accessible
    }
};

class DerivedLevel2 : public Derived1Level1, public Derived2Level1 {
public:
    void f() {
        std::cout << "f() in Derived1Level2" << std::endl;

        g(); // 如果Derived1Level1和Derived2Level1继承Base时不加virtual此处会提示对g的调用不明确,
             // 因此虚拟继承主要是为了解决此类菱形继承的问题
        Derived1Level1::h();
    }
};

int main()
{
    Base b;

    Derived1Level1 d1l1;

    Derived2Level1 d1l2;

    DerivedLevel2 dl2;
    dl2.f();

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值