C ++解决没有虚拟继承的钻石继承

时间:2017-07-06 06:03:22

标签: c++ c++11 multiple-inheritance diamond-problem

我有以下不编译的钻石类结构:

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)。还有其他解决方案吗?我可以随意更改MyParentClassEvilDiamond;但是,EvilDiamond必须从MyParentClassNotMineToTouch继承,MyParentClass必须从Base继承,并且不得从EvilDiamond继承。

2 个答案:

答案 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
}