【问题标题】:Why doesn't 'using A::X' avoid ambiguity with multiple inheritance?为什么“使用 A::X”不能避免多重继承的歧义?
【发布时间】:2020-09-18 06:28:10
【问题描述】:

这类似于this questionthis one,但我认为(希望!)不同之处足以值得解释。

我有一个复杂的配置框架,装饰器类用于实现一些常见的简单操作(例如在调用类 Set 访问器时进行标记)。我正在尝试引入一个新的装饰器(而不是组合),它本身“应该”继承自同一个常见的“Set-flagging”装饰器。

我遇到了“从派生类到基类的模棱两可的转换”,我试图解决这个问题的尝试都失败了。 我肯定遗漏了一些明显的东西。

这是一个非常简单的示例,没有我的所有框架内容。

class A {
public:
  template <class T> void Set(T& arg, T val);
  bool Ready() const;
};

class B : private A {
  // Does stuff where I want to flag Set() actions
};

class C : public B, public A {
  // This class needs the B interface, and the Set()-flagging
public:
  void SetParam(double val) { Set(param, val); }

private:
  double param;
};

请注意,我最初使用 A 的虚拟继承,但实际上我需要保持 B 的“Set-flag”与 C 的“Set-flag”不同,因此我在上面进行了尝试。

上面的私有继承是我第一次尝试避免歧义。我还尝试在 C 中引入 using 指令:

class C : public B, public A {
  // This class needs the B interface, and the Set()-flagging
  using A::Set;
  using A::Ready;
};

这不会改变错误。我从搜索中了解到,在检查公共/私人状态之前会发现歧义。但我认为明确的using 指令可以解决它。为什么不呢?我是否需要进入并在任何地方明确使用A::Set(...)A::Ready()

【问题讨论】:

  • 问题在于 A 是模棱两可的——它可能是直接基址 AB::A
  • 你有什么理由不能只是:class B : public Aclass C : public BB 必须只能从 A 继承 private 吗?
  • “但我认为显式的using 指令会解决它。” -- 指令并没有解决它,而是让你不用输入A::Set(...)A::Ready() 无处不在。指令using A::Set; 意味着(或多或少)“当你看到Set 时,将其读作A::Set”。如果指令没有解决歧义,那么也不会写出A::Set
  • @Frodyne 我原来有过。在我的实际应用程序中,事实证明,在 C 中,我需要将 B 的参数更改与 A 的所有其他更改分开跟踪。我可能最终不得不使 C 具有 B,但我想确定我无法为此使用装饰器模式。

标签: c++ multiple-inheritance ambiguity


【解决方案1】:

两种解决方案。

如果你真的想保持私有和多重继承:

class A {
public:
    void Set() {};
    bool Ready() const {};
};

class B : private A {
};

class C : public B, public A {
public:
    void SetParam() { C::A::Set(); }
};

或者如果不需要,那就更简单的一个:

class A {
public:
    void Set() {};
    bool Ready() const {};
};

class B : public A {
};

class C : public B {
public:
    void SetParam() { Set(); }
};

【讨论】:

  • 这些看起来像是我概述的类层次结构的正确“结构”解决方案。对于我的特定应用程序,我将 C 类更改为使用组合:它直接从 A 继承,但使用 B 数据成员以保持两个“Set-flag”值不同。
猜你喜欢
  • 2018-03-20
  • 2010-09-29
  • 2014-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-13
  • 2016-05-07
相关资源
最近更新 更多