我注意到了一些我认为非常有趣的行为。
考虑下面的示例代码,我试图使其尽可能通用:
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中删除私有(private)模板方法,则main()中的两个函数调用都将是有效的。
现在我的问题是这是否是C++规范的一部分,或者这是否是编译器特定的行为(已使用Visual Studio 2017 ver 15.5.7编译器进行了测试)。
最佳答案
在这里发出错误的C++是有效的。
参见[class.member.lookup]:
因此,首先选择适当的重载(模板),然后进行访问控制,这将导致编译器错误。