【问题标题】:Why won't the C++ compiler disambiguate between an inherited public and an inherited private method with the same name?为什么 C++ 编译器不能区分继承的公共方法和继承的同名私有方法?
【发布时间】:2011-11-04 19:14:32
【问题描述】:

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

【问题讨论】:

    标签: c++ inheritance multiple-inheritance


    【解决方案1】:

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

    fb.Bar::Baz()
    

    【讨论】:

    • 但要注意它的限定语法有两件事:1) 控件名称查找 2) 禁用动态调度(不是在这种特殊情况下,但它可能)。
    【解决方案2】:

    为了允许这样做,需要考虑您是否处于允许调用私有方法的上下文中。如果允许,则调用:

    fb.Baz()
    

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

    【讨论】:

      【解决方案3】:

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

      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】:

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

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

        【讨论】:

        • 这是故意的。它并没有使编译器变得更简单,相反,它稍微复杂了一点,因为必须将访问作为附加步骤进行检查。
        【解决方案5】:

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

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

        【讨论】:

          猜你喜欢
          • 2020-07-14
          • 2014-11-24
          • 2011-03-11
          • 1970-01-01
          • 2011-05-31
          • 1970-01-01
          • 1970-01-01
          • 2015-03-07
          相关资源
          最近更新 更多