2017-07-03 79 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