3

我不明白为什么我需要重新定义覆盖的基类方法。

在这里,如果我在派生类中注释 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();
}
4

3 回答 3

3

foo(int) 隐藏了基类名称。像这样修复它:

class Derived: public Base {
public:
    using Base::foo;
    void foo(int i) {
    }
    void test() {
        foo();
        foo(1);
    }
};
于 2013-03-19T12:13:17.127 回答
3

foo采用单个int参数的声明将隐藏fooBase. 你可以像这样带一个隐藏的名字Base

class Derived: public Base {
public:
    using Base::foo; // Pulls foo from Base
    void foo(int i) {
    }
    void test() {
        foo();
        foo(1);
    }
};
于 2013-03-19T12:13:25.503 回答
1

正如其他人已经说过的那样,答案是foo派生类型中的隐藏foo基类型中的 。扩展一下这意味着问题是查找具有一组规则,编译器必须应用这些规则,直到找到标识符。一旦找到名称,它就不会继续寻找更好的匹配,它会尝试使用它所看到的。

当你在里面Derived::test键入foo()时,编译器必须解析foo,这可能是任何东西(类型、[成员]变量、[成员]函数......)。为此,它开始查找内部可用的内容Derived::test,并且那里没有foo声明。然后将搜索范围扩大到完整类型Derived,并发现有一个成员函数foo。此时它停止*。如果它没有找到Derived::foo(int),它将继续将搜索扩展到基础,然后是命名空间,然后是其他命名空间......

*在这种特殊情况下,由于标识符解析为函数,因此在 ADL 启动时会采取额外的步骤(或者如果将非基本类型的参数传递给函数,则会启动)。

于 2013-03-19T12:35:24.430 回答