以下代码有错误:最后一行应为
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);
}
答案 0 :(得分:4)
您无法通过更改其参数来覆盖虚拟成员函数。也就是说,Derived::g(int)
不覆盖Base::g()
。
想象一下你是编译器。您看到函数调用bp->g(1)
,并且您知道bp
是Base*
。因此,您向Base
查找名为g
的函数,该函数采用int
的参数。你发现了什么?没有!没有一个。
只有当基类中的某个函数是虚拟的时,才会考虑该对象的动态类型。所以让我们考虑一下bp->f()
。它知道bp
是Base*
,因此它查找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)会导致编译时错误。