C++菱形繼承問題


在C++中,什么叫做菱形繼承問題(也可以叫鑽石問題),怎么避免它?

假設我們有類B和類C,它們都繼承了相同的類A。另外我們還有類D,類D通過多重繼承機制繼承了類B和類C。因為上述圖表的形狀類似於鑽石(或者菱形),因此這個問題被形象地稱為鑽石問題(菱形繼承問題)。現在,我們將上面的圖表翻譯成具體的代碼:

#include<iostream>

class Animal{
private:
    int weight;
public:
    virtual int getWeight()
    {
        return this->weight;
    }
};

class Tiger :  public Animal{};

class Lion : public Animal{};

class Liger : public Tiger, public Lion{};

int main()
{
    Liger lg;
    lg.getWeight();
}

在我們的繼承結構中,我們可以看出Tiger和Lion類都繼承自Animal基類。所以問題是:因為Liger多重繼承了Tiger和Lion類,因此Liger類會有兩份Animal類的成員(數據和方法),Liger對象"lg"會包含Animal基類的兩個子對象。

所以,你會問Liger對象有兩個Animal基類的子對象會出現什么問題?再看看上面的代碼-調用"lg.getWeight()"將會導致一個編譯錯誤。這是因為編譯器並不知道是調用Tiger類的getWeight()還是調用Lion類的getWeight()。所以,調用getWeight方法是不明確的,因此不能通過編譯。

解決方法一:

使用虛繼承,C++會保證對於每個Liger對象,只有一個Animal類的子對象會被創建。

#include<iostream>

class Animal{
private:
    int weight;
public:
    virtual int getWeight()
    {
        return this->weight;
    }
};

class Tiger : virtual public Animal{};

class Lion : virtual public Animal{};

class Liger : public Tiger, public Lion{};

int main()
{
    Liger lg;
    lg.getWeight();
}

解決方法二:

指定域

#include<iostream>

class Animal{
private:
    int weight;
public:
    virtual int getWeight()
    {
        return this->weight;
    }
};

class Tiger : public Animal{};

class Lion : public Animal{};

class Liger : public Tiger, public Lion{};

int main()
{
    Liger lg;
    lg.Lion::getWeight();
}

當存在多繼承時,雖然我們盡可能地保證不同類中地成員變量和成員函數命名不沖突,但是想菱形繼承仍有可能發生。

所以我們應該盡可能少地使用多繼承,只有在比較簡單或者實在有必要時才使用,能用單一繼承解決的問題就不要使用多繼承。也正是這個原因,C++之后的很多面向對象的語言,例如Java、C#、PHP等,都不支持多繼承。

 

參考鏈接:

1. https://blog.csdn.net/tounaobun/article/details/8443228

2. https://blog.csdn.net/zhanghow/article/details/53587460


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM