2017-07-03 91 views
-1

我知道這被問了很多次,但我找不到適合我的問題的解決方案。繼承導致模糊轉換

我有類似下面的代碼:

#include <iostream> 
#include "stdafx.h" 

using namespace std; 

class A        //can not modify 
{ 
public: 
    double ComputeValue(double val) 
    { 
     return val + 1; 
    } 
}; 
class B : public A {};    //can not modify 
class C : public A {}; 
class D : public B, public C {}; 
class E        //can not modify 
{ 
public: 
    double GetValue(A *a) 
    { 
     double x = 4; 
     return a->ComputeValue(x); 
    } 
    double DoSomething() 
    { 
     return GetValue(new D()); 
    } 
}; 

int main() 
{ 
    E *e = new E(); 
    cout << e->DoSomething(); 
    return 0; 
} 

我從 'd * A *的' 在DoSomething的錯誤不明確的轉換。我知道我可以用「鑽石繼承」來解決這個問題。但是我不能改變A類或者B類或者E類,因爲它們已經在很多地方使用過了,並且類似於鑽石繼承中描述的變化可能會在應用程序中產生問題。所以我可以修改只是C類或D類。

爲了闡明我需要做的是從A:C繼承一個新類,並讓D類繼承這個新類而不會在F中產生問題。我是尋找一種方法在D類中阻止A從C的繼承。另外,爲了使B類繼承自C或修改B來完成C所做的一切並不是一種選擇。

+0

'a.ComputeValue(x);'帶'a'指針? – StoryTeller

+0

請不要把C++看作是Java。除非您瞭解其含義,否則不要使用'new'來創建對象。 – StoryTeller

+0

我發佈了該代碼,讓我知道我的問題是什麼。該代碼沒有任何價值,它只是一張大圖的最小化腳本。由於機密性問題,我無法發佈實際的代碼。如果你對我所問的問題有一個可能的解決方案,我將不勝感激。 – student

回答

1

既然你把所有的修改限制,您可以通過靜態鑄造D指向任何的基類,CB的解決歧義。這樣,編譯器會知道你是指其中A實例(這將是基類的鑄造型):

class F 
{ 
    public: 
    bool DoSomething() 
    { 
     double s; 
     E *e = new E(); 
     D *d = new D(); 
     s = e->GetValue(static_cast<C*>(d)); 
    } 
} 

但是這種解決方案是時代錯誤的99%。在D中,您將擁有A的兩個不同副本(因爲其他人已經評論,因爲鑽石問題),因此使用鑄造解決方案調用GetValue將返回類別可能具有的兩個GetValue之一,從而導致可能的問題。


另一種解決方案是改變D類。而不是使用繼承的,可用的組合物:

class D{ 
public: 
    D(): 
     b_ptr(new B), 
     c_ptr(new C), 
     a_ptr(b_ptr) //Or c_ptr, the one you want. 
    { 
    } 
    double ComputeValue(double val) 
    { 
     //Use a_ptr, which you have already initialized from constructor 
    } 

    A* a() {return a_ptr;} 
    B* b() {return b_ptr;} 
    C* c() {return c_ptr;} 
private: 
    B *b_ptr;  
    C *c_ptr;  
    A *a_ptr; //Initialized from any of the above. 
} 

但同樣,完美的解決方案將解決鑽石問題,但你必須改變BC類。 這些只是解決方法,這可能會導致未來更難以解決問題。

+0

該解決方案實際上是一個很好的解決方法。我感謝幫助和建議。 – student

1

這是鑽石繼承問題,您需要繼承A virtual ly。

class B: virtual public A{} 
class C: virtual public A{} 

更多看到How does virtual inheritance solve the "diamond" (multiple inheritance) ambiguity?https://isocpp.org/wiki/faq/multiple-inheritance#mi-diamond

+0

我已經寫了,因爲發展原因,我無法修改B. ...... – student

+0

@student你是什麼意思?你不能改變你正在使用的代碼? – Curious

+0

由於A,B,E和F的廣泛使用,可能會出現多個問題,例如此處所述的問題:https://stackoverflow.com/a/25689818/4621626。該應用程序開發的風險是:( – student