0

我的 C++ 程序有一个非常特殊的情况。

查看以下类设置:

class Base1 {
  public: void baseMethod();
}

class Base2 : public Base1 {
  ...
}

class Common {
  public: void commonMethod();
}

class Derived1 : public Base1, public Common {
  ...
}

class Derived2 : public Base2, public Common {
  ...
}

Base1并且Base2对我来说是不变的,因为它们是图书馆的一部分。

我想要实现的是两者Derived1共享Derived2相同的方法commonMethod(),所以我使用Common具有该方法的类作为Derived1and的公共基础Derived2

现在的问题是commonMethod()应该包含一个baseMethod()Base1! 在Derived1- 或 -对象的上下文中,Derived2这是合法的,但如何定义该方法Common

我知道,如果我将声明Base2为虚拟派生类Base1并且与 相同Common,那应该不是问题(至少对于Derived2,不确定Derived1)。但是因为我无法修改Base2,所以无论如何都是不可能的。

也让Common继承 fromBase2然后Derived1Derived2完全 fromCommon不起作用,因为我不想Derived1继承 from Base2

然后我想到的是在里面做一个dynamic_cast commonMethod()

void Common::commonMethod() {
  ...
  Base1* self = dynamic_cast<Base1*>(this);
  if(self) {
    self->baseMethod();
  }
  ...
}

这似乎可行,但我不确定这是否是一个“不错”的解决方案......

你有什么想法可以让它变得更好吗?或者你认为这个解决方案一点也不差?:)

4

2 回答 2

1

如果 的唯一目的Common是提供该方法的通用实现,则可以使用 CRTP 模式并将其模板化到基础类型上。此时,您可以决定将其保留为DerivedX类型的多个基是否有意义,或者线性化继承层次结构是否有意义:

// Option1
template <typename Derived>
struct Common {
   void commonFunction() { ... static_cast<Derived*>(this)->foo(); ... }
};
struct Derived1 : Base1, Common<Derived1>

// Option2 (not strictly CRTP, but close)
template <typename Base>
struct Common : Base {
   void commonFunction() { ... this->foo(); ... } // keep the this-> here
};
struct Derived1 : Common<Base1>
于 2013-08-29T04:49:20.247 回答
1

如果我是你,我会选择组合而不是多重继承,即定义common为派生类的成员对象。

class Base1 {
  public: void baseMethod();
}

class Base2 : public Base1 {}

class Common {
  public: 
     Common(Base1 *base): m_base(base) {}
     void Common::commonMethod()
     {
        m_base->baseMethod();
     }
  private:
     Base1 *m_base;
}

class Derived1 : public Base1
{
  public:
     Derived2(): m_common(this) {}
  private:
     Common m_common;
}

class Derived2 : public Base2
{
  public:
     Derived2(): m_common(this) {}
  private:
     Common m_common;
}

不过,这样做有潜在的风险。由于成员 object( Common) 是在外部 object(Derived1Derived2) 之前首先构造的,因此您要确保在的构造函数中没有调用来自该Derivedx对象的方法。Common

于 2013-08-29T04:53:19.490 回答