如果在派生类中有相同的函数原型,会发生什么



我有一个使用继承的非常简单的代码,并且我的基类和派生类中有相同的函数原型。我不理解最后的结果(pB->bar()(,因为我认为由于pB指向派生类型对象(在delete之后(,它应该调用D::bar()

#include <iostream>
class B {
public:
virtual void foo() { std::cout << "B:foo" << std::endl; }
void bar() { std::cout << "B:bar" << std::endl; }
};
class D : public B {
public:
virtual void foo() override { std::cout << "D:foo" << std::endl; }
void bar(){ std::cout << "D:bar" << std::endl;}
};
int main() {
B* pB = new B;
pB->foo();
pB->bar();
delete pB;
pB = new D;
pB->foo();
pB->bar();
delete pB;
}

结果是:

B:foo
B:bar
D:foo
B:bar

您已将virtual用于foo,但未使用bar。这个程序演示了这个关键字的效果:它发出信号,考虑对象的动态或运行时类型。如果没有它,编译器只使用静态或编译时类型信息生成直接函数调用。

关键字virtual为类函数创建一个虚拟表,然后当您使用指向类的指针时,程序会检查类的类型,并尝试在虚拟表中查找函数foo。

当你调用bar时,程序会检查bar实现的类指针,因为指针是B类型的,所以会调用B的函数栏。

你可以编写

D* pD = new D;
pD->bar();

bar()不是virtual,因此对它的调用在编译时使用它所调用的类型静态解析。它在运行时不会像您所期望的那样动态解析,类似于foo(),即virtual

通过B*指针调用bar()将调用B::bar(),而通过D*指针调用它将改为调用D::bar()pBB*,这就是为什么pB->bar()调用B::bar(),而不管pB指向B还是D对象。这是一个静态调用。

最新更新