为什么赢了';t C++;编译器是否在继承的公共方法和具有相同名称的继承的私有方法之间消除歧义? 我对C++编译器为什么不接受这个问题感到困惑: class Foo { private: void Baz() { } }; class Bar { public: void Baz() { }; class FooBar : public Foo, public Bar { }; void main() { FooBar fb; fb.Baz(); }

为什么赢了';t C++;编译器是否在继承的公共方法和具有相同名称的继承的私有方法之间消除歧义? 我对C++编译器为什么不接受这个问题感到困惑: class Foo { private: void Baz() { } }; class Bar { public: void Baz() { }; class FooBar : public Foo, public Bar { }; void main() { FooBar fb; fb.Baz(); },c++,inheritance,multiple-inheritance,C++,Inheritance,Multiple Inheritance,gcc给出的错误是: request for member ‘Baz’ is ambiguous candidates are: void Bar::Baz() void Foo::Baz() 但是我想要Bar::Baz(),因为Foo::Baz()是私有的,这不是很明显吗?为什么编译器不能在这里消除歧义?这并不明显-您可能希望调用私有成员(如果可能的话) 在形式上,语言规则规定首先解析名称,然后选择最佳重载。只有在这之后,才会检查可访问性。名称解析分两个

gcc给出的错误是:

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

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

这并不明显-您可能希望调用私有成员(如果可能的话)


在形式上,语言规则规定首先解析名称,然后选择最佳重载。只有在这之后,才会检查可访问性。

名称解析分两个阶段工作。首先查找名称,然后检查名称的访问权限。如果名称查找不明确,则从不考虑访问


至于原因,也许这是一个深思熟虑的语言设计,但我认为更可能的是,这只是为了简化解析姓名的过程。这些规则已经极其复杂。

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

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和<代码>,你总是可以调用非虚公共接口<代码> UsHyMe()/Cuth>,但是你的派生类提供了一个私有虚拟化的实现。

< P>。为了允许这一点,它需要考虑你是否在一个允许你调用私有方法的上下文中。如果允许,则调用:

fb.Baz()

可能具有完全不同的功能,这取决于您是从公共上下文还是从私有上下文调用它。这与语言的工作方式并不完全一致。

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

fb.Bar::Baz()

这是故意的。它并没有使编译器变得更简单,相反,它稍微复杂一些,因为访问必须作为一个附加步骤进行检查。但是要小心,因为限定语法有两个作用:1)控件名称查找2)禁用动态分派(不是在这种特殊情况下,但它可能会)。