【问题标题】:C++ Template Method Overloading and Class Access with PolymorphismC++ 模板方法重载和多态类访问
【发布时间】:2018-03-09 16:23:14
【问题描述】:

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

考虑以下示例代码,我尽量保持通用性:

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 编译器测试的)。

【问题讨论】:

    标签: c++ templates visual-studio-2017 polymorphism overloading


    【解决方案1】:

    在此处发出错误是有效的 C++。

    参见[class.member.lookup]:

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

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

    【讨论】:

    • 我明白了,这就是我所怀疑的。太糟糕了,因为这使得使用多态性同时保留这种模式更加麻烦。然后再次有更好的方法。感谢您指出 C++ 标准中的相关条款。
    • 通常,如果我编写一个公共函数的私有版本,我会在私有函数名称后面附加“helper”。
    • 是的,重命名私有方法也是我最终要做的。通常我会尽量避免重命名函数,因为重载是更明显的事情。
    猜你喜欢
    • 1970-01-01
    • 2015-05-07
    • 2021-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-19
    • 1970-01-01
    相关资源
    最近更新 更多