在C ++中我们需要双重调度/访问者的情况究竟发生了什么

时间:2019-09-27 12:51:53

标签: c++ double-dispatch

我了解解决方案的实现以及双重分发/访问者模式,但是我不了解在编译时和运行时我们需要这种模式会发生什么。

例如此代码:

#include <iostream>

class A {
public:
};
class B : public A {
};

class F {
public:
    virtual inline void operator()(const A&) const noexcept {
        std::cout << "FxA" << std::endl;
    }
    virtual inline void operator()(const B&) const noexcept {
        std::cout << "FxB" << std::endl;
    }
};

class G : public F {
public:
    virtual inline void operator()(const A&) const noexcept {
        std::cout << "GxA" << std::endl;
    }
    virtual inline void operator()(const B&) const noexcept {
        std::cout << "GxB" << std::endl;
    }
};

void by_const_ref(const F& f, const A& a) {
    f(a);
}

int main() {
    by_const_ref(F(), A());
    by_const_ref(F(), B());
    by_const_ref(G(), A());
    by_const_ref(G(), B());

    return 0;
}

在没有双调度的情况下,对by_const_ref的第二次和第四次调用不会将B()解析为A对象。

本文摘自https://en.wikipedia.org/wiki/Double_dispatch#Double_dispatch_in_C++,我了解它涉及名称修饰,运行时的编译时以及vtable解析,但是我没有找到确切的方法。

对于名称处理部分,我查看了已编译的对象,但没有发现任何特殊之处。

对于vtable,我将其与g ++ -fdump-lang-class一起转储了,看起来好像那里也没有太多信息。

因此,我的要求。我想了解到底发生了什么,以及可能如何检查这种行为(使用nm等工具,检查vtable,机器代码?)

1 个答案:

答案 0 :(得分:4)

你太深了,这很简单。

C ++虚函数基于单个参数this的类型启用动态调度。顾名思义,双重调度是基于两个参数类型的动态调度。由于该语言没有提供此功能,因此,Visitor模式仅使用内置的一次调度两次,并将每个动态参数依次用作this

可以想象,通过继续进行此音乐椅游戏,直到所有动态参数都被this一次并在最终通话之前被正确调度为止,来实现访客执行三重调度或更多操作。