我知道这次被问过多次,但我找不到适合我问题的解决方案。
我有类似下面的代码:
#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所做的一切都不是一种选择。
答案 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
指针静态转换为任何基类C
或B
来解决歧义。这样,编译器将知道您引用的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
但同样,完美的解决方案是解决钻石问题,但为此你必须改变C
或const 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
类。
这些只是解决方法,可能会导致未来更难解决问题。