这与函数重载有什么关系?

2024-01-09

This http://coliru.stacked-crooked.com/a/d85bba3aa84a89a3基本上是中给出的示例的副本Item 21. Overriding Virtual Functions在赫伯·萨特的书中Exceptional C++.

#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页顶部作者给出的解释(重点是我的):

有趣的是,即使 Base* pb 指向 Derived 对象,这调用 Base::f( double ),因为重载解析是 对静态类型(此处为 Base)完成,而不是动态类型(此处为 衍生的).

我的理解是调用pb->f(1.0)是一个虚拟调用,并且Base::f(double)是最终的覆盖者f(double) in Derived。这与函数重载有什么关系?


这里微妙的部分是虚拟方法是一种机制dispatch函数调用,而重载是影响函数调用的功能解决通话的。

也就是说,对于任何调用,编译器都需要弄清楚应该调用哪个方法(解决它);之后,在逻辑上不同的操作中,它需要生成调用该方法的正确实现的代码(调度它)。

从定义Base and Derived上面给出的我们可以很容易地推断出如果f(double)被称为Base*那么该调用应该优先于基本实现分派给任何派生的重写(如果适用)。但回答这个问题与回答一个完全不同的问题

当消息来源说pb->f(1.0),哪个方法名为f应该用来解析方法调用?

正如 Sutter 所解释的,规范指出,在解析调用时,编译器将查看名为的方法f在指向的静态类型上声明pb;在这种情况下,静态类型是Base*所以重载(不是覆盖!)声明Derived根本不会被考虑。但是,如果调用解析为的方法是virtual然后提供了可能的实现Derived将按预期使用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

这与函数重载有什么关系? 的相关文章

随机推荐