我有三个不同的编译器,我用来编译这段代码.其中一个(我最信任的那个)警告Derived中的函数隐藏了Base中的函数.其他编译器(一个是Visual C++)没有警告.如果我启用/ Wall或/ W4,Visual C++甚至不会发出警告.
我倾向于认为这是编译器中的一个错误,它会发出警告,因为它编译代码.如果它确实没有覆盖基函数,那么当我创建派生模板的实例时它应该给出错误.
任何人都可以确认这应该如何表现?
struct Base
{
virtual void Func(float f) = 0;
};
template <typename T>
struct Derived : Base
{
virtual void Func(T f){}
};
int main()
{
Derived<float> d;
d.Func(0);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
什么时候Derived实例化float我得到意外的警告.当Derived被实例化与int我得到一个错误,符合市场预期.
它确实被覆盖了.您可以使用override关键字在C++ 11中轻松说服自己,如果不覆盖该函数,则不允许编译代码:
struct Base
{
virtual void Func(float f) = 0;
virtual ~Base() = default; // to silence warnings
};
template <typename T>
struct Derived : Base
{
void Func(T f) override {} // will fail to compile if not overriding
};
int main()
{
Derived<float> d;
d.Func(0);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这里有实例.
请注意,在前C++ 11中,您可以virtual通过在派生类中更改其签名来意外隐藏基本函数,因此即使您标记派生函数virtual代码仍然编译,但不再是多态,请参见此处的此类示例.不幸的是,g ++没有提供任何警告,即使是-Wall -Wextra.这就是为什么override在编译时实际执行真正覆盖的更安全的方法.