3

以下代码有bug:最后一行应该是
bp->g();
问题是,如果我注释掉那行,bp->f()实际上调用了Derived版本,所以我假设编译器将bp视为类Derived,那么为什么在调用g时,编译器将bp其视为Base指针。

谢谢!

#include <iostream>
using namespace std;

class Base {
public:
    virtual void f() const { cout << "Base::f()\n"<< endl; }
    virtual void g() const { cout << "Base::g()\n"<< endl; }
};

class Derived : public Base {
public:
    void f() const {cout << "Derived::f()" << endl; }
    void g(int) const {cout << "Derived::g()" << endl; }
};

int main() {
    Base* bp = new Derived;
    bp->f();
    bp->g(1);
}
4

4 回答 4

4

You can't override a virtual member function by changing its arguments. That is, Derived::g(int) is not overriding Base::g().

Imagine you are the compiler. You see the function call bp->g(1) and you know that bp is a Base*. So you look up Base for a function called g that takes an argument that is an int. What do you find? Nothing! There isn't one.

It's only when a function is found in the base class to be virtual that it will then consider the dynamic type of the object. So let's consider the call bp->f(). It knows that bp is a Base*, so it looks up a member function of Base called f that takes no arguments. It finds Base::f() of course, and sees that it is virtual. Because it is virtual, it then looks up the same function in the dynamic type of the object, which is Derived. It finds Derived::f() and calls that one instead.

于 2013-04-07T16:00:43.387 回答
1

This happens because Derived::g does not override Base::g. It is a completely independent method that happens to have the same name. The two methods are unrelated because they take different arguments.

Thus when you call bp->g(1), the fact that Base also happens to have a method called g is completely irrelevant.

于 2013-04-07T16:00:44.347 回答
0

your Derived class now doesn't override the Base::g():

class Derived : public Base {
public:
//...
    void f() const {cout << "Derived::f()" << endl; }
    void g() const {cout << "Derived::g()" << endl; } // <- add this, it is overriding Base::g() const
//...
};

the method: void g(int) const {cout << "Derived::g()" << endl; } is autonomic method of your Derived class, it doesn't override Base::g because none of Base::g takes int argument.

于 2013-04-07T16:05:43.217 回答
0

实际上,您的示例应该在 bp->g(1); 行中给出编译时错误;在这两种情况下,编译器都将 bp 视为具有 2 个虚函数 void f() 和 void g() 的 Base*,其中 f() 在 Derived 中被覆盖,因此当您调用 bp->f() 时,将通过 vtable 调用 Derived 版本。但是 Base 中没有 void g(int),因此 bp->g(1) 会导致编译时错误。

于 2013-04-07T16:09:56.530 回答