开发者

Why won't the C++ compiler disambiguate between an inherited public and an inherited private method with the same name?

I'm confused as to why the C++ compiler won't accept this:

  class Foo { 
    private: void B开发者_如何学Goaz() { }
  };

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

  class FooBar : public Foo, public Bar { };

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

The error gcc gives is:

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

but isn't it obvious that I want Bar::Baz(), since Foo::Baz() is private? Why won't the compiler disambiguate here?


Name resolution works in two stages. First the name is looked up then the name is checked for access. If the name look up is ambiguous then the access is never considered.

As to why, maybe it's a deliberate language design, but I think more likely it's just to simplify the process of resolving names. The rules are fiendishly complicated already.


It's not obvious - you might have wanted to call the private member (if that was possible).

Formally, the language rules say that the name is resolved first and the best overload is selected. Only after that is there a check for accessibility.


In order to allow this, it would need to consider whether or not you are in a context that allows you to call a private method or not. If this were allowed then the call:

fb.Baz()

could have completely different functionality depending on whether you were calling it from a public or private context. And that's not really inline with the way the language works.


As others have said, first the name is looked up, then access restrictions are applied. You can work around this by explicitly calling the method you wish, as in

fb.Bar::Baz()


Access restrictions don't affect inheritance. You always inherit everything from all base classes. In your case that may seem unnecessary, but consider a slightly modified version where the private function is virtual:

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

Now for any Base& you can always call the non-virtual public interface use_me(), but your derived classes provide the implementation by means of a private virtual.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜