为什么C ++编译器不会在继承的公共和具有相同名称的继承私有方法之间消除歧义?

时间:2011-08-26 19:40:19

标签: c++ inheritance multiple-inheritance

我很困惑为什么C ++编译器不接受这个:

  class Foo { 
    private: void Baz() { }
  };

  class Bar {
    public: void Baz() { 
  };

  class FooBar : public Foo, public Bar { };

  void main() {
    FooBar fb;
    fb.Baz();
  }

gcc给出的错误是:

 request for member ‘Baz’ is ambiguous
 candidates are: void Bar::Baz()
                 void Foo::Baz()

但是我想要Bar :: Baz()并不明显,因为Foo :: Baz()是私有的吗?为什么编译器不会在这里消除歧义?

5 个答案:

答案 0 :(得分:7)

名称解析分两个阶段进行。首先查找名称,然后检查名称以进行访问。如果名称查找不明确,则永远不会考虑访问。

至于为什么,也许这是一个刻意的语言设计,但我认为更可能只是简化名称的解析过程。规则已经非常复杂了。

答案 1 :(得分:3)

这并不明显 - 您可能想要致电私人会员(如果可能的话)。

正式地,语言规则说首先解析名称并选择最佳重载。只有在那之后才检查可访问性。

答案 2 :(得分:2)

为了实现这一点,需要考虑您是否处于允许您调用私有方法的上下文中。如果允许,则拨打电话:

fb.Baz()

可能具有完全不同的功能,具体取决于您是从公共或私有环境调用它。而这与语言的运作方式并不完全一致。

答案 3 :(得分:1)

访问限制不会影响继承。您始终从所有基类继承所有内容。在你的情况下,这似乎是不必要的,但考虑一个稍微修改的版本,其中私有功能是虚拟的:

class Base
{
  virtual void secret_power() { /* innocent default */ }
public:
  void use_me() { secret_power(); }
};

class Derived : public Base
{
  virtual void secret_power() { /* overriding implementation here */ }
};

现在对于任何Base&,您始终可以调用非虚拟公共接口use_me(),但您的派生类通过私有虚拟提供实现。

答案 4 :(得分:1)

正如其他人所说,首先查找名称,然后应用访问限制。您可以通过显式调用所需的方法来解决此问题,如

fb.Bar::Baz()