C++派生类同名方法调用疑问:d.foo(2)为何匹配double参数版本?
问题原因分析
- 核心原因是C++的**名字隐藏(Name Hiding)**规则,和多态无关,属于作用域查找和重载决议的范畴。
- C++对成员函数做名字查找时,会从当前类的作用域开始匹配:当你通过Derived类型的对象d调用foo时,编译器首先在Derived的作用域内查找名为foo的函数,一旦找到
void foo(double)这个匹配的名字,就会终止查找,不会再去父类Base的作用域查找其他同名函数。所以Base类的void foo(int)根本没有进入本次调用的重载候选集,哪怕int参数的匹配度更高也不会被选中。 - 确定调用Derived::foo(double)后,编译器会对传入的int类型字面量2做隐式类型转换,将其转为double类型,因此最终执行的是double参数版本的foo。
扩展说明
- 你代码中第一处调用
p->foo(2.1)输出int的原因也和查找规则有关:p是Base*类型,查找foo时只会在Base的作用域查找,找到的是虚函数foo(int),2.1会被隐式转为int值2,又因为Derived没有重写签名为void foo(int)的虚函数,所以最终调用的是Base的foo实现。 - 如果想要让父类的同名函数也参与Derived的重载决议,可以在Derived类中主动引入父类的foo声明:
class Derived : public Base { public: using Base::foo; // 引入Base作用域的所有foo函数到当前类 void foo(double) { cout << "double" << endl; } };
修改后d.foo(2)就会匹配到参数更契合的Base::foo(int),输出int。
内容的提问来源于stack exchange,提问作者Jack Peng
相关产品推荐
相关产品推荐

