我遇到了一个可怕的钻石问题。 提醒一下,这是这个问题的经典类层次结构:
B
/ \
C1 C2
\ /
D
要解决这个问题,标准解决方案是让C1和C2使用虚拟继承从B继承。
我的问题是B和C1来自我无法修改的SDK。 下面的示例我无法使 SubClassB 从 Base 虚拟地继承。 类:PureVirtualBase,Base和SubClassB来自我使用的SDK。我无法修改它们。 SubClassA和Leaf是我的自定义类。我可以改变它们。
PureVirtualBase(SDK)
|
Base(SDK)
/ \
SubClassA SubClassB(SDK)
\ /
Leaf
在 SubClassB 无法更改为使用 Base 的虚拟继承的情况下。怎么应该这样:
class PureVirtualBase
{
public:
PureVirtualBase()
{
cout<<"<<PureVirtualBase::PureVirtualBase" << endl;
cout<<">>PureVirtualBase::PureVirtualBase" << endl;
}
virtual int f_PureVirtualBase()=0;
};
class Base : public PureVirtualBase
{
public:
Base(std::string id) {
cout<<"<<Base::Base:"<<id << endl;
m_id=id;
cout<<">>Base::Base:"<<m_id << endl;
}
virtual int f_PureVirtualBase() {
cout<<"Base::f_PureVirtualBase" << endl;
return 1;
}
private:
std::string m_id;
};
class SubClassA: public virtual Base
{
public:
SubClassA(): Base("From SubClassA") {
cout<<"<<SubClassA::SubClassA" << endl;
cout<<">>SubClassA::SubClassA" << endl;
}
};
class SubClassB: public Base
{
public:
SubClassB():Base("From SubClassB") {
cout<<"<<SubClassB::SubClassB" << endl;
cout<<">>SubClassB::SubClassB" << endl;
}
};
class Leaf: public SubClassA, public SubClassB
{
public:
Leaf():SubClassA(), SubClassB(), Base("From Leaf") {
cout << "<<Leaf::Leaf" << endl;
cout << ">>Leaf::Leaf"<< endl;
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Leaf myleaf;
myleaf.f_PureVirtualBase();
return a.exec();
}
任何提示?
回复评论的更多信息
我的目标架构比原始问题中提供的示例稍微复杂一些:
PureVirtualBase(SDK)
|
Base(SDK)
|
--SubClassA
--SubClassB(SDK)
--SubClassC(SDK)
--SubClassD(SDK)
LeafOne:继承自SubClassA和SubClassB(SDK)
LeafTwo:继承自SubClassA和SubClassC(SDK)
LeafThree:继承自SubClassA和SubClassD(SDK)
SubClassA是我自己的私人代码。它提供自定义功能。它应该能够被SDK方法视为Base实例。 这个类不会被实例化,但是在执行某些处理时,它可以同时处理LeafOne,LeafTwo和LeafThree。
答案 0 :(得分:4)
这表明您的设计存在问题,最简单的答案是首先避免钻石。您为示例代码选择的名称已经足够严重,难以说明您可能实际想要做什么,但无论如何都要重新考虑您是否需要从父母双方继承,以及是否这是有道理的。
继承是OO语言中滥用最多的构造之一,它确实解决了一个问题,但在其他地方用作golden hammer。很多时候,你手上的东西是screw,而不是钉子,正确的工具不是锤子。
答案 1 :(得分:1)
如果您真的遇到这些设计约束,我肯定会直接从B中继承一个将C1和C2作为复合组件的类。不幸的是,这需要手动镜像他们的界面(希望它很小,或者你可以将它限制为你需要的)并代理到子组件。它不漂亮,但除非你能在其他地方强制执行一些设计,否则你真的没有多少选择。
当然,一个缺点是你没有你正在寻找的类型标识(子类不满足C1或C2的“isa”),这可能足以将这种方法从水中吹走。
这不漂亮。但我希望,鉴于你的限制,它可能是“最不好”的解决方案。