简体   繁体   中英

Why doesn't 'using A::X' avoid ambiguity with multiple inheritance?

This is similar to this question and this one , but I think (hope!) different enough to deserve an explanation.

I have a complex configuration framework, with decorator classes used to implement some common, simple actions (like flagging when a class Set accessor is called). I'm trying to introduce a new decorator (rather than a composition), which itself "should" inherit from that same common "Set-flagging" decorator.

I'm running into "ambiguous conversion from derived class to base class", and my attempts to work around it have failed. I'm missing something obvious, I'm sure.

Here's a very simple example, without all my framework stuff.

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

Note that I original used virtual inheritance of A, but in practice I need to keep the "Set-flag" for B distinct from the "Set-flag" for C, hence my attempt above.

The private inheritance above was my first attempt to avoid the ambiguity. I also tried introducing using directives in C:

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

This doesn't change the error. I understand from searching that the ambiguity is caught before the public/private state is checked. But I thought that the explicit using directives would resolve it. Why doesn't it? Do I need to go in and use A::Set(...) or A::Ready() explicitly everywhere?

Two solutions.

If you really want to keep the private and multiple inheritance:

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

class B : private A {
};

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

Or if that is not needed, then a simpler one:

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

class B : public A {
};

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM