代码之家  ›  专栏  ›  技术社区  ›  Deconimus

C++模板方法重载和多态性类访问

  •  2
  • Deconimus  · 技术社区  · 7 年前

    我注意到一些我认为很有趣的行为。

    考虑以下示例代码,我试图尽可能保持通用性:

    class Base
    {
    public:
      virtual void func() {}
    };
    
    class Subclass : public Base
    {
    public:
      void func() {}
    };
    
    class ApplyingClass
    {
    public:
      static void callFunc(Base& base) { base.func(); }
    private:
      template <class T>
      static void callFunc(T& t) { t.func(); }
    };
    
    int main()
    {
      Subclass s;
      Base& b = s;
    
      // Error: ApplyingClass::callFunc(T& t) with T=Subclass is private.
      ApplyingClass::callFunc(s);
    
      // works
      ApplyingClass::callFunc(b);
    
      return 0;
    }
    

    似乎在main()内部,由于存在模板方法,编译器将模板“ApplyingClass::callFunc(T&T)”视为与函数调用“ApplyingClass::callFunc(s)”相匹配,并抛出一个错误,因为无法从其类外部访问该方法。

    这似乎合乎逻辑,但我希望编译器仍然使用“ApplyingClass::callFunc(Base&Base)”,因为方法签名合适,而且这是唯一 可到达的 拟合方法。

    让我的观点更进一步;如果要从ApplyingClass中删除私有模板方法,main()中的两个函数调用都是有效的。

    我现在的问题是,这是C++规范的一部分,还是编译器特定的行为(这是使用Visual Studio 2017版本15.5.7编译器测试的)。

    1 回复  |  直到 7 年前
        1
  •  2
  •   AndyG    7 年前

    C++在这里发出错误是有效的。

    请参见[类.成员.查找]:

    如果明确找到重载函数的名称, 过载解决也发生在 访问控制

    因此,首先选择适当的重载(模板),然后进行访问控制,这会导致编译器错误。