2

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

例如这段代码:

#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,机器代码?)

4

1 回答 1

4

你太深入了,它更简单。

C++ 虚函数支持基于单个参数类型的动态调度,this. 双重调度,顾名思义,就是根据两个参数的类型进行动态调度。由于语言不提供此功能,因此访问者模式仅使用内置的单次调度两次,this依次使用每个动态参数。

this您可以通过继续这个抢椅游戏,直到所有动态参数都已经被一次并且在最终调用之前被正确调度,您可以想象实现一个执行三重调度或更多调度的访问者。

于 2019-09-27T13:10:43.340 回答