继承导致模糊转换

时间:2017-07-03 05:56:18

标签: c++ qt

我知道这次被问过多次,但我找不到适合我问题的解决方案。

我有类似下面的代码:

#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;
}

我在DoSomething中得到了从'D *到A *'的错误模糊转换。我知道我可以使用“钻石继承”来解决这个问题。但我无法更改A类或B类或E类,因为它们已经在很多位置使用过,并且钻石继承中描述的更改可能会在应用程序中产生问题。所以我只能修改C类或D类。

澄清我需要做的是创建一个继承自A:C的新类,并使D类继承这个新类而不会在F中引起问题。我正在寻找一种方法来阻止D类继承来自C。也是为了使B类从C继承或修改B来做C所做的一切都不是一种选择。

2 个答案:

答案 0 :(得分:1)

这是钻石继承问题,你需要从A virtual继承。

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

答案 1 :(得分: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 1}} 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. } 类。而不是使用继承,使用组合:

B

但同样,完美的解决方案是解决钻石问题,但为此你必须改变Cconst conv = require('iconv-urlencode'); let input = 'Est%E1+%E9+uma+sala+de+teste'; console.log( conv.decode(input, 'latin-1') ); // Está é uma sala de teste 类。 这些只是解决方法,可能会导致未来更难解决问题。