C++指向成员函数的指针是否会执行虚函数分发?
问题解答
虚分发发生的原理
你对成员函数指针的认知存在误区:指向虚成员函数的指针并不会直接绑定基类对应函数的实体地址。
对于普通非虚成员函数,取地址得到的成员函数指针确实存储的是函数的直接执行地址,调用时不会触发虚分发;但对于虚函数,执行&Base::func取地址操作时,得到的成员函数指针存储的是该虚函数在所属类虚表中的索引偏移值,而非固定的函数地址。
你代码中(bptr->*func_ptr)()的实际执行流程如下:
- 第一步:从
bptr指向的对象内存首地址读取虚表指针_vptr,由于bptr的动态类型是Derived,因此该虚表指针指向Derived类的虚表 - 第二步:从
func_ptr中取出预存的虚函数索引,到上述Derived类的虚表中查找对应的函数地址,得到的就是Derived::func的地址 - 第三步:调用查到的函数地址,因此输出
Derived func called
如果需要强制跳过虚分发调用基类版本,需要显式指定类作用域:bptr->Base::func(),该写法不会触发虚表查找。
C++标准依据
该行为在ISO/IEC 14882(C++标准)的[expr.mptr.oper](成员指针运算符)章节有明确规定:当通过.*或->*运算符调用的成员函数为虚函数时,虚分发机制正常生效,最终调用的函数由调用对象的动态类型决定,和成员函数指针本身声明所属的类无关。
内容的提问来源于stack exchange,提问作者Karen Baghdasaryan
相关产品推荐
相关产品推荐

