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

99封情书 提交于 2021-02-04 15:34:42

问题


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

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

  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?


回答1:


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.




回答2:


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.




回答3:


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.




回答4:


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.




回答5:


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()


来源:https://stackoverflow.com/questions/7209738/why-wont-the-c-compiler-disambiguate-between-an-inherited-public-and-an-inher

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!