为什么派生类必须定义重写的基类方法

时间:2013-03-19 12:11:04

标签: c++

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

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

3 个答案:

答案 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启动时会采取额外的步骤(或者如果存在传递给非基本类型的参数,则会启动。功能)。