我希望这可行:
template <typename T> class MyBaseClass
{
public:
MyBaseClass();
virtual ~MyBaseClass();
void DoSomething(const T& myClass);
// Implemented in .cpp file
virtual void DoSomething(int n, const T& myClass);
// Implemented in .cpp file
};
class MyDerivedClass : public MyBaseClass<int>
{
public:
virtual void DoSomething(int n, const int& myInt);
// Implemented in .cpp file
};
......以及我的代码中的其他地方:
int i;
MyDerivedClass myClass;
myClass.DoSomething(i);
然而,它没有;相反,它无法编译错误说(在Visual C ++的情况下)
error C2660: 'int::DoSomething' : function does not take 1 arguments
...即使显然是在基类中声明的DoSomething版本, 只接受一个参数。如果我用派生类中的两个参数重新定义DoSomething,那么错误就会消失。
我犯了什么微妙的C ++规则,并且有一种优雅的解决方法吗?
答案 0 :(得分:2)
C ++中的方法隐藏了超类的所有方法,这些方法具有相同的名称。在你的例子中
virtual void DoSomething(int n, const int& myInt);
派生类阴影中的
void DoSomething(const T& myClass);
在基类中,因此在使用派生类型的对象时,后一种方法不可见。
这种行为与Java等其他语言完全不同,其中一种方法不会影响具有相同名称但签名不同的其他方法,并且最初可能会感觉有点反直觉。这样做的原因只是C ++的名称查找规则:一旦在作用域中找到了名称,就不会考虑其他作用域。在您的示例中,编译器在派生类中查找DoSomething(const T&)
,并停止在超类中查找更多方法。
有一个简单的补救措施:要使所有DoSomething
方法再次可见,请在派生类中使用using
指令:
using MyBaseClass<int>::DoSomething;
using
指令通过将方法拉入派生类的范围,使得被遮蔽的方法再次可见。现在,名称查找将在派生类的范围内找到正确的DoSomething(int, const int&)
方法。