我很困惑为什么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()是私有的吗?为什么编译器不会在这里消除歧义?
答案 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()