为何通过基类成员函数调用虚函数仍执行派生类版本?
为什么基类成员函数内调用虚函数,仍会执行派生类的实现?
在下面的C++代码片段中,foo()并非直接通过Base类指针调用(通常认为这种方式才会触发动态绑定),而是从Base的成员函数run()内部调用,但最终执行的却是Derived类的foo()版本,这是为什么?
#include <iostream> struct Base{ void run(){ std::cout << "Base run" << "\n"; foo(); } virtual void foo(){ std::cout << "Base foo" << "\n"; }; }; struct Derived : Base{ void foo() override{ std::cout << "Derived foo" << "\n"; } }; int main(){ Derived d; Base* ptr = &d; ptr->run(); }
程序输出:
Base run Derived foo
原因解析
核心逻辑是:C++中虚函数的动态绑定,取决于调用该函数的对象的实际类型,和调用发生的位置(基类成员函数内还是外部)无关。
具体拆解过程:
- 你用
Base* ptr = &d;定义的指针,静态类型是Base*,但它指向的对象的实际类型是Derived。 - 调用
ptr->run()时,因为run()不是虚函数,所以直接执行Base类的run()实现(静态绑定)。 - 但在Base::run()里调用
foo()时,这个调用等价于this->foo()——这里的this指针指向的是当前实际对象,也就是Derived实例,所以this的实际类型是Derived*。 - 由于
foo()是虚函数,C++会通过对象内部的虚函数表(vtable),根据this指向的实际对象类型,动态绑定到Derived类的foo()实现。
简单说,只要是虚函数,不管在哪里调用,最终执行哪个版本,只看当前正在操作的对象到底是哪个类的实例。
内容的提问来源于stack exchange,提问作者CD86
相关产品推荐
相关产品推荐

