问题标签 [dynamic-dispatch]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
2603 浏览

java - 在没有双重调度/访问者模式的情况下解决 Java 的静态方法调度

我正在使用一个Foo提供这些方法的类:

由于 Java 在 non-receiver 参数上静态分派,我不能只传递 my value(这是一个Object,但可能具有动态类型Goo)并依赖 JVM 动态选择“正确”方法。

这是我目前(丑陋)的解决方法:

有没有更好的方法可以在不修改Foo(包含重载方法的类)中的代码的情况下做到这一点?

0 投票
3 回答
637 浏览

c# - 反射或动态调度

我正在编写一个由两个具体解析器扩展的抽象文件解析器(C#)。两者都需要执行多次检查。目前抽象解析器中有一个验证方法,它使用反射来调用所有名称以'test'开头的方法。这样添加检查就像添加名称以“test”开头的方法一样简单。

现在最近我对反射的使用有一些评论,使用动态调度更好。我的问题是,为什么使用反射,你将如何实现它?另外我应该如何使用动态调度来解决这个问题?

0 投票
2 回答
1544 浏览

c# - 基于变量值的动态方法调度

长的转换语句通常是不受欢迎的。解决方案是使用多态性。但是,如果我打开的东西不是类型代码怎么办?我想做的是用类似这样的东西替换switch语句......

这将取代以下...

有任何想法吗?从理论上讲,我认为您可以完全取消“if/switch”语句,而只需调用根据表达式的值自动绑定的方法。

0 投票
3 回答
3413 浏览

c++ - 基于模板参数在 C++ 中模拟动态调度

为了这个问题,这被大大简化了。假设我有一个层次结构:

我想要一个带有签名的非模板函数:

a其中函数结果的具体类型与b其中较大者的类型相同Precision;类似于以下伪代码:

其中A和分别是和B的具体类型。我想独立于有多少实例进行操作。我想避免使用大量的比较表,尽管 RTTI 的答案很好。有任何想法吗?abfunctionDerivedtypeid()

0 投票
10 回答
695 浏览

c++ - 为什么 C++ 不允许您请求指向最派生类的指针?

(这个问题可能应该参考 Stroustrup 来回答。)

能够请求指向最派生类的指针似乎非常有用,如下所示:

但是这种机制在 c++ 中没有提供。为什么?

更新,激励示例:

假设您没有 Base 和 Derived 以及 Processor,而是:

但这在 C++ 中很难做到,需要像访问者模式这样的创造性解决方案。那么,问题是:为什么在 C++ 中这样做很棘手,而像“CAST_TO_MOST_DERIVED”这样的东西会让它变得更简单?

更新:维基百科无所不知

我认为 Pontus Gagge 有一个很好的答案。从关于Multiple Dispatch的 Wikipedia 条目中添加这一点:

“Stroustrup 提到他喜欢The Design and Evolution of C++中的 Multi-methods 概念,并考虑在 C++ 中实现它,但声称无法找到有效的示例实现(类似于虚函数)并解决一些可能的类型歧义问题. 他接着说,虽然这个特性仍然很好,但它可以使用双重调度或基于类型的查找表来近似实现,如上面的 C/C++ 示例中所述,因此对于未来的语言来说是一个低优先级特性修订。”

作为背景,您可以阅读有关Multi-Methods的一些摘要,这比我提到的那种调用要好,因为它们可以正常工作。

0 投票
4 回答
915 浏览

c++ - c++ 虚拟调用 w/ vtable 实现中的多线程竞争条件的怀疑

我怀疑在某些 C++ 多线程情况下可能存在竞争条件,涉及 vtable 动态调度实现中的虚拟方法调用(为此,vtable 指针作为隐藏成员存储在具有虚拟方法的对象中)。我想确认这是否真的是一个问题,并且我指定了 boost 的线程库,以便我们可以假设一些参考框架。

假设一个对象“O”有一个 boost::mutex 成员,它的整个构造函数/析构函数和方法都被范围锁定(类似于 Monitor 并发模式)。线程“A”在没有外部同步的情况下在堆上构造对象“O”(即没有包含“新”操作的共享互斥锁,它可以与其他线程同步;但请注意,仍然存在“内部,Monitor”互斥锁其构造函数的作用域)。然后,线程 A 通过同步机制将指向“O”实例(它刚刚构建)的指针传递给另一个线程“B”——例如,同步的读写器队列(注意:只有指向对象正在被传递——而不是对象本身)。施工后,

线程“B”从同步队列中读取对象“O”的指针值,然后立即离开保护队列的临界区。然后线程“B”对对象“O”执行虚方法调用。这是我认为可能出现问题的地方。

现在,我对动态调度的[很可能的] vtable 实现中的虚拟方法调用的理解是,调用线程“B”必须取消引用指向“O”的指针,以便获得存储为其对象的隐藏成员的 vtable 指针,并且这发生在进入方法体之前(自然是因为在访问存储在对象本身中的 vtable 指针之前,要执行的方法体不能安全准确地确定)。假设上述陈述对于这样的实现可能是正确的,这不是竞争条件吗?

由于在任何内存可见性保证操作发生之前(即获取对象“O”中的成员变量mutex),线程“B”(通过解除指向位于堆中的对象“O”的指针)检索vtable指针,那么不确定“B”会感知“A”最初写在对象“O”的构造上的vtable指针值,对吗?(即,它可能会感知到垃圾值,从而导致未定义的行为,对吗?)。

如果上述是有效的可能性,这是否意味着对线程之间共享的专有内部同步对象进行虚拟方法调用是未定义的行为?

而且——同样——由于标准对 vtable 实现是不可知的,如何保证 vtable 指针在虚拟调用之前对其他线程安全可见?我想人们可以在外部同步(“外部”,例如,“围绕共享互斥锁()/解锁()块”)构造函数调用,然后至少在每个线程中进行初始虚拟方法调用,但这似乎是一些非常不和谐的编程。

所以,如果我的怀疑是真的,那么一个可能更优雅的解决方案是使用内联的非虚拟成员函数来锁定成员互斥体,然后转发到虚拟调用。但是——即使那样——我们能否保证构造函数在 lock() 和 unlock() 的范围内初始化了 vtable 指针来保护构造函数本身?

如果有人可以帮助我澄清这一点并确认/否认我的怀疑,我将不胜感激。

编辑:演示以上内容的代码

-- 在第 (4) 点,我的印象是“线程 A”写入内存的 vtable 指针值可能对“线程 B”不可见,因为我看不出有任何理由假设编译器会生成代码,以便将 vtable 指针写入构造函数的锁定互斥块中。

例如,考虑多核系统的情况,其中每个内核都有一个专用缓存。根据这篇文章,缓存通常是积极优化的,并且——尽管强制缓存一致性——如果不涉及同步原语,则不会对缓存一致性强制执行严格的排序。

也许我误解了这篇文章的含义,但这并不意味着“A”将 vtable 指针写入构造对象(并且没有迹象表明这种写入发生在构造函数的锁定互斥块中)可能在“B”读取 vtable 指针之前不会被“B”感知?如果 A 和 B 都在不同的内核上执行(“A”在 core0 上,“B”在 core1 上),缓存一致性机制可能会重新排序 core1 缓存中 vtable 指针值的更新(使其一致的更新与 core0 的缓存中的 vtable 指针的值,“A”写)这样它发生在“B”的读取之后......如果我正确解释了这篇文章。

0 投票
1 回答
672 浏览

c++ - 访问者模式是区分 C++ 中参数类型的最快方法吗?

访问者模式是在 C++ 中完成方法参数类型识别(有效地单次调度参数,而不是成员的类)的最快方法吗?我可能知道我想对未知子类型的元素调用的确切方法,因此总是不希望像V::visit(A *)in那样进行额外的虚拟方法调用A::accept(V &v) { v.visit(this); }

我想要以下功能等效的东西,但成本为 O(1),这是 AFAIK 无法使用 dynamic_cast<> 或 typeid() 梯子,因为std::type_info不能是 constexpr/switchable。

我在这里有什么选择?感谢您的建议!

编辑:更改了示例代码以通过字段提供结果,这样不同的方法类型就不需要多个签名。谢谢,莫里斯!

最终决定:除了不喜欢访问者模式的强制双重调度成本之外,我还想避免接口膨胀的重载foo(),但我认为没有已知的干净模式可以做到这一点。我最终只是做了直接的静态重载,然后就收工了。无论如何,我想将重载封装在一个函数中可能充其量是一个值得商榷的目标。谢谢,莫里斯的回应。

0 投票
2 回答
4640 浏览

python - python中的动态调度和继承

我正在尝试修改 Guido 的多方法(动态调度代码):

http://www.artima.com/weblogs/viewpost.jsp?thread=101605

处理继承和可能乱序的参数。

例如(继承问题)

有没有比迭代检查每个项目的 super() 直到找到一个更好的方法?

例如(参数排序问题)我从碰撞检测的角度考虑这个问题。

例如

都应该触发

我正在寻找一个“优雅”的解决方案。我知道我可以通过所有的可能性暴力破解我的方式,但我试图避免这种情况。在坐下来敲定解决方案之前,我只是想获得一些输入/想法。

谢谢

0 投票
1 回答
89 浏览

architecture - 什么是识别哪些特定游戏对象正在碰撞的好方法?

这是关于物理引擎的。一旦发生碰撞,它会返回两个游戏对象正在碰撞的信息。所有实体,如玩家、怪物、子弹等都是从 GameObject 派生(继承)的。

什么是识别哪些特定游戏对象正在碰撞的好方法?

枚举:我曾考虑过使用枚举,但是一旦您开始添加更多实体,就无法跟踪所有可能的组合。

编辑:我在这里找到了 C# 的潜在解决方案:http: //blogs.msdn.com/b/laurionb/archive/2009/08/13/multimethods-in-c-4-0-with-dynamic.aspx

但是,如果我必须在 C++ 中执行此操作,我该怎么做?

0 投票
1 回答
232 浏览

c++ - 如果调用非虚拟实现,函数会通过 vtable 调度吗?

说我有以下内容:

回调调用是通过 vtable 调用还是直接函数调用,因为它在函数签名中未标记为虚拟?