我不明白为什么我需要重新定义覆盖的基类方法。
这里,如果我在派生类中注释foo()方法,它就不会编译。
感谢您的解释。
class Base {
public:
void foo() {
}
};
class Derived: public Base {
public:
#define compile_ok
#ifdef compile_ok
// if this method is commented, it does not compile
void foo() {
Base::foo();
}
#endif
void foo(int i) {
}
void test() {
foo();
foo(1);
}
};
void testOverride() {
Derived d;
d.test();
}
答案 0 :(得分:3)
您的foo(int)
隐藏基类名称。修复如下:
class Derived: public Base {
public:
using Base::foo;
void foo(int i) {
}
void test() {
foo();
foo(1);
}
};
答案 1 :(得分:3)
您声明foo
采用单个int
参数将隐藏foo
中名为Base
的所有函数。您可以从Base
中隐藏名称,如下所示:
class Derived: public Base {
public:
using Base::foo; // Pulls foo from Base
void foo(int i) {
}
void test() {
foo();
foo(1);
}
};
答案 2 :(得分:1)
正如其他人已经说过的那样,答案是派生类型中的foo
隐藏基本类型中的foo
。为了扩展一点意味着问题是查找具有一组规则,并且编译器必须应用这些规则直到找到标识符。一旦找到名称,它将不会继续寻找更好的匹配,它会尝试使用它看到的内容。
当你在Derived::test
内输入foo()
时,编译器必须解析foo
,它可能是任何东西(类型,[成员]变量,[成员]函数......)。为此,它开始查看Derived::test
内可用的内容,并且那里没有声明foo
。然后它将搜索范围扩展为完整类型Derived
,并发现存在成员函数foo
。此时它停止 * 。如果它没有找到Derived::foo(int)
,它会继续将搜索扩展到基础,然后是命名空间,然后是其他命名空间......
* 在这种特殊情况下,因为标识符解析为函数,所以当ADL启动时会采取额外的步骤(或者如果存在传递给非基本类型的参数,则会启动。功能)。