我希望这能起作用:
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++ 规则,有没有一种优雅的方法来解决这个问题?
最佳答案
C++ 中的方法会隐藏父类(super class)中具有相同名称的所有 方法。在你的例子中
virtual void DoSomething(int n, const int& myInt);
在派生类阴影中
void DoSomething(const T& myClass);
在基类中,因此后一个方法在使用派生类型的对象时不可见。
这种行为与 Java 等其他语言有很大不同,Java 中的方法不会隐藏具有相同名称但不同签名的其他方法,并且一开始可能会感觉有点违反直觉。原因很简单,就是 C++ 的名称查找规则:一旦在某个作用域中找到某个名称,就不再考虑其他作用域。在您的示例中,编译器在派生类中找到 DoSomething(const T&)
,并停止在父类(super class)中查找其他方法。
有一个简单的补救措施:要使所有 DoSomething
方法再次可见,请在派生类中使用 using
指令:
using MyBaseClass<int>::DoSomething;
using 指令通过将被隐藏的方法拉入派生类的范围,使它们再次可见。现在,名称查找将在派生类的范围内找到正确的 DoSomething(int, const int&)
方法。
关于c++ - 重写派生类中的某些重载,但不重写其他重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24607585/