重写?上溯造型?

时间:2013-04-07 15:57:38

标签: c++ virtual override

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

谢谢!

#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 个答案:

答案 0 :(得分:4)

您无法通过更改其参数来覆盖虚拟成员函数。也就是说,Derived::g(int) 覆盖Base::g()

想象一下你是编译器。您看到函数调用bp->g(1),并且您知道bpBase*。因此,您向Base查找名为g的函数,该函数采用int的参数。你发现了什么?没有!没有一个。

只有当基类中的某个函数是虚拟的时,才会考虑该对象的动态类型。所以让我们考虑一下bp->f()。它知道bpBase*,因此它查找Base的{​​{1}}成员函数,该函数不带参数。它当然找到了f,并且发现它是虚拟的。因为它是虚拟的,所以它在对象的动态类型中查找相同的函数,即Base::f()。它会找到Derived并调用它。

答案 1 :(得分:1)

这是因为Derived::g未覆盖Base::g。它是一个完全独立的方法,碰巧具有相同的名称。这两种方法无关,因为它们采用不同的论点。

因此,当您致电bp->g(1)时,Base碰巧有一个名为g的方法的事实完全无关紧要。

答案 2 :(得分:0)

您的Derived类现在不会覆盖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
//...
};

方法:void g(int) const {cout << "Derived::g()" << endl; }是Derived类的自主方法,它不会覆盖Base::g,因为Base::g都没有int参数。

答案 3 :(得分:0)

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