为什么“使用A :: X”不能避免多重继承的歧义?

问题描述

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

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

我遇到了“从派生类到基类的模棱两可转换”,而解决它的尝试失败了。 我确定我缺少明显的东西。

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

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的“设置标志”与C的“设置标志”区分开,因此我在上面进行了尝试。

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

class C : public B,and the Set()-flagging
  using A::Set;
  using A::Ready;
};

这不会更改错误。从搜索中我了解到,在检查公共/私有状态之前已发现歧义。但是我认为显式using指令可以解决该问题。为什么不呢?我需要进去在任何地方显式使用A::Set(...)A::Ready()吗?

解决方法

两种解决方案。

如果您真的想保留私有继承和多重继承:

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(); }
};