我有以下不编译的钻石类结构:
class Base{
int a;
public:
virtual void doSomething();
};
class NotMineToTouch : public Base {};
class MyParentClass : public Base {};
class EvilDiamond : public NotMineToTouch, public MyParentClass {};
// I need these methods (that I cannot necessarily edit) to work for an EvilDiamond
void processBase (Base* b) { b->doSomething; /*...*/} // Cannot edit
void processParent (MyParentClass* p) { p->doSomething; /*...*/} // Can edit
void processNotMine (NotMineToTouch* n) { n->doSomething; /*...*/} // Cannot edit
我知道正常的解决方案是从Base
虚拟继承;但是,我不能更改NotMineToTouch
(或Base
)。还有其他解决方案吗?我可以随意更改MyParentClass
和EvilDiamond
;但是,EvilDiamond
必须从MyParentClass
和NotMineToTouch
继承,MyParentClass
必须从Base
继承,并且不得从EvilDiamond
继承。
答案 0 :(得分:3)
我挑战以下断言:
EvilDiamond必须继承MyParentClass和NotMineToTouch
您可以沿着这些方向做某事(取决于您的架构):
class EvilDiamond;
class NotMineToTouchImpl : public NotMineToTouch {
EvilDiamond* tgt_;
public:
NotMineToTouchImpl(EvilDiamond* tgt) : tgt_(tgt) {}
... implement NotMineToTouch here, using tgt_ where you would have used this
};
class MyParentClassImpl : public MyParentClass {
EvilDiamond* tgt_;
public:
MyParentClassImpl(EvilDiamond* tgt) : tgt_(tgt) {}
... implement Base here, using tgt_ where you would have used this
};
class EvilDiamond {
friend class NotMineToTouchImpl;
friend class MyParentClassImpl;
// Creating permanent instances of the API classes
// may or may not be appropriate in your case.
NotMineToTouchImpl nmti_;
MyParentClassImpl pci_;
public:
EvilDiamond () : nmti_(this), pci_(this) {}
NotMineToTouchImpl* getAsNotMineToTOuch() {return &nmti_;}
MyParentClassImpl * getAsParentClass() {return &pci_;}
};
答案 1 :(得分:2)
由于您不使用虚拟继承,因此您没有钻石
您目前有一些" Y" 继承(EvilDiamond
有2 Base
)。
在不更改类的情况下,您可以添加重载以指示编译器执行操作:
void processBase (EvilDiamond* evil) {
processBase(static_cast<NotMineToTouch*>(evil)); // Use NotMineToTouch::Base
processBase(static_cast<MyParentClass*>(evil)); // Use MyParentClass::Base
}