【问题标题】:Solve diamond problem without virtual inheritance解决没有虚拟继承的菱形问题
【发布时间】:2019-10-14 17:03:11
【问题描述】:

情况如下:

class A
{
public:
  A();
  void actionA();
private:
  int a;
};

class B1
  : public A
{
  ...
};

class B2
  : public A
{
  ...
};

class OrthogonalFeature
  : public A
{
  void orthogonalFeature();
};

class C1
  : public B1
  , public OrthogonalFeature
{
    ...
};

class C2
  : public B2
  , public OrthogonalFeature
{
    ...
};

class User
{
public:
  void run() {
    c.actionA();
    c.orthogonalFeature();
  }
private:
  MyNeededType c; // c is either C1 or C2
};

User 类需要拥有一个可以执行actionA()actionB() 的对象。

因此,我可能想创建类MyNeededType,它需要从A 和(B1B2)继承,我遇到了菱形问题(数据成员a 不明确) .解决这个问题的常用方法是使用虚拟继承。但是,对于这个项目,出于性能原因,我不能使用虚拟继承(请只接受它的表面价值)。

所以我有一个问题。可能有帮助的是 User 类将仅在我拥有的 2 个现有类上运行:C1C2。所以我想到的另一个选择是让C1C2A继承,并在这些派生类中重新实现orthogonalFeature,而不是继承OrthogonalFeature。所以没有钻石。看起来是这样的:

class C1
  : public B1
{
   public:
     void orthogonalFeature();
};

class C2
  : public B2
{
    void orthogonalFeature();
};

我喜欢那个解决方案,但是我怎样才能在 User 中指定 c 的类型?我觉得我需要创建一个类型,这意味着:这个类是C1C2。但我不知道这存在于c++中?

欢迎任何想法,谢谢!

【问题讨论】:

  • “拥有”是什么意思?
  • 我的意思是它是它的数据成员的一部分。
  • 除了提供更多信息的好主意之外,还请考虑将您的问题视为 XY 问题。 meta.stackexchange.com/questions/66377/what-is-the-xy-problem 即通过以您正在考虑的特定方式解决这个抽象的“钻石问题”,您实际上想要实现什么。
  • 正如@Yunnosch 所说。每当有人声称虚函数查找速度太慢时 我想说,“证明一下”。如果你的时间很紧,你根本不应该使用函数调用。
  • “但是,对于这个项目,出于性能原因,我不能使用虚拟继承(请仅按面值接受)。”虚拟继承的唯一性能问题是程序员在合理使用它时的性能。如果使用正确,则不会有固有的运行时性能损失。无论如何,这让我觉得是一个 XY 问题,而不是一个有效的问题。

标签: c++ c++14 diamond-problem


【解决方案1】:

对您来说,快速访问 A 数据成员有多重要?最终,虚拟继承使您可以轻松访问 A::a,但对 B2 和 B1 中的几乎所有其他内容都付出了一定的代价。

你能在不使用钻石的情况下得到你想要的分享 A::a 的效果吗?在 COM 模型中,所有接口类都使用从 IUnknown 接口继承的简单继承,但是实例化类必须实现最终的“真正的基类”功能才能获得“注册”的 IUnknown。当然,该模型中没有数据成员。

您可以简单地设置B1: public trueAB2: public indirectA,然后在您的实现中,有一个模板包装器“激活”indirectA 以找到trueA。您实际上还可以让您的实现包装器从 trueA、B1、B2 派生,并将间接 A 的 B1 和 B2 实例都修复到它?

但请注意,这依赖于 B1 和 B2 的构造函数不引用 A,因为它尚未初始化。

有可能肮脏地破解indirectA的构造函数以“知道”它实际上是在C:B2中实例化的,并推断出C:B1:A或C:A,并且您可以通过使用模板推送周围的定义,也许有一点 CRTP?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-09
    • 1970-01-01
    • 2011-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-23
    • 2014-10-12
    相关资源
    最近更新 更多