2017-07-06 89 views
3

我有以下的鑽石類結構無法編譯:C++解決菱形繼承如果沒有虛擬繼承

class Base{ 
    int a; 
public: 
    virtual void doSomething(); 
}; 

class NotMineToTouch : public Base {}; 

class MyParentClass : public Base {}; 

class EvilDiamond : public NotMineToTouch, public MyParentClass {}; 

// I need these methods (that I cannot necessarily edit) to work for an EvilDiamond 
void processBase (Base* b) { b->doSomething; /*...*/} // Cannot edit 

void processParent (MyParentClass* p) { p->doSomething; /*...*/} // Can edit 

void processNotMine (NotMineToTouch* n) { n->doSomething; /*...*/} // Cannot edit 

我知道正常的解決方案是從Base幾乎繼承;但是,我不允許更改NotMineToTouch(或Base)。還有其他解決方案嗎?我可以隨意改變MyParentClassEvilDiamond;然而,EvilDiamond必須從MyParentClassNotMineToTouch繼承,而MyParentClass必須從Base繼承,並且不得從EvilDiamond繼承。

+0

我只得到一個警告並不是一個錯誤。你能否給我們提供你得到的實際編譯器錯誤,或者發佈代碼來重現問題。順便說一句,如果你不使用虛擬繼承,它不是鑽石。虛擬繼承是將兩個基礎合併爲一個創建鑽石形狀的基礎,如果您在圖表中繪製該基礎。 – Eelke

+0

我們在Bases和MyParentClass的其他地方調用了虛方法getA()(在代碼中我不總是被允許改變)。它可能不是鑽石繼承,但它肯定是鑽石問題(請參閱標籤上的說明)。我在EvilDiamond上調用getA()時發生編譯器錯誤: 錯誤:成員'getA'的請求不明確 注:候選者爲:virtual int Base :: getA() note:virtual int Base :: getA() –

+0

Can當你傳遞對象時,你沒有轉換到正確的類型? –

回答

3

我挑戰了以下斷言:

EvilDiamond must inherit from MyParentClass and NotMineToTouch

你可能可以做這些方針的東西(這取決於你的體系):

class EvilDiamond; 

class NotMineToTouchImpl : public NotMineToTouch { 
    EvilDiamond* tgt_; 
public: 
    NotMineToTouchImpl(EvilDiamond* tgt) : tgt_(tgt) {} 

    ... implement NotMineToTouch here, using tgt_ where you would have used this 
}; 

class MyParentClassImpl : public MyParentClass { 
    EvilDiamond* tgt_; 
public: 
    MyParentClassImpl(EvilDiamond* tgt) : tgt_(tgt) {} 

    ... implement Base here, using tgt_ where you would have used this 
}; 

class EvilDiamond { 
    friend class NotMineToTouchImpl; 
    friend class MyParentClassImpl; 

    // Creating permanent instances of the API classes 
    // may or may not be appropriate in your case. 
    NotMineToTouchImpl nmti_; 
    MyParentClassImpl pci_; 
public: 
    EvilDiamond() : nmti_(this), pci_(this) {} 

    NotMineToTouchImpl* getAsNotMineToTOuch() {return &nmti_;} 
    MyParentClassImpl * getAsParentClass() {return &pci_;} 
}; 
+0

編輯原文。我有其他方法可以接受基地,我需要通過一個邪惡的鑽石。 –

2

您不必爲鑽石你不使用虛擬繼承。
你目前有一些「Y」繼承(EvilDiamond有2 Base)。

不改變你的類,您可以添加過載指示編譯器做什麼:

void processBase (EvilDiamond* evil) { 
    processBase(static_cast<NotMineToTouch*>(evil)); // Use NotMineToTouch::Base 
    processBase(static_cast<MyParentClass*>(evil)); // Use MyParentClass::Base 
}