#include <iostream> #include <complex> using namespace std; class Base { public: virtual void f(int); virtual void f(double); virtual ~Base() {}; }; void Base::f(int) { cout << "Base::f(int)" << endl; } void Base::f( double ) { cout << "Base::f(double)" << endl; } class Derived: public Base { public: void f(complex<double>); }; void Derived::f(complex<double>) { cout << "Derived::f(complex)" << endl; } int main() { Base* pb = new Derived; pb->f(1.0); delete pb; }
代码打印Base :: f(double),我没有问题.但我无法理解作者在第122页的顶部给出的解释(重点是我的):
Interestingly,even though the Base* pb is pointing to a Derived
object,this calls Base::f( double ),because overload resolution is
done on the static type (here Base),not the dynamic type (here
Derived).
我的理解是,调用pb-> f(1.0)是一个虚拟调用,Base :: f(double)是Derived中f(double)的最终覆盖.这与函数重载有什么关系?
解决方法
也就是说,对于任何调用,编译器需要确定应该调用哪个方法(解析它);之后,在逻辑上不同的操作中,它需要生成调用该方法的正确实现的代码(调度它).
根据上面给出的Base和Derived的定义,我们可以很容易地推断,如果在Base *上调用f(double),那么应该将调用分派给任何派生的覆盖(如果适用)而不是基本实现.但回答这个回答的问题完全不同于
When the source says
pb->f(1.0)
,which of the methods namedf
should be used to resolve the method call?
正如Sutter解释的那样,规范说当解析调用时,编译器将查看在pb指向的静态类型上声明的名为f的方法;在这种情况下,静态类型是Base *所以在Derived上声明的重载(不是覆盖!)根本不会被考虑.但是,如果调用解析的方法是虚拟的,那么Derived上提供的可能实现将按预期使用.