标签: dynamic-dispatch

GHC是否使用存在类型的动态调度?

下面的代码是否使用动态分派,因为它在C++或Java中被理解?

据我所知,在最后一行,编译器不可能在编译时知道调用(==)的实现,但代码编译并产生正确的结果.有人可以解释一下,这背后有什么样的实现(比如vptr)?

{-# LANGUAGE ExistentialQuantification #-}

data Value = A Int

data ForallFunc = forall a. Eq a => Forall (Value -> a) 

unpackA (A int) = int

equalityTest :: Value -> Value -> ForallFunc -> Bool            
equalityTest arg1 arg2 (Forall unpacker) =
  let a1 = unpacker arg1
      a2 = unpacker arg2 in
    a1 == a2
Run Code Online (Sandbox Code Playgroud)

haskell existential-type dynamic-dispatch

4
推荐指数
2
解决办法
168
查看次数

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

长开关的声明往往令人不悦.解决方案是使用多态.但是,如果我正在打开的东西不是类型代码呢?我想做的是用这样的东西替换switch语句......

public void HandleString(string s = "Hello")
{
 ...
}

public void HandleString(string s = "Goodbye")
{
 ...
}

...
HandleString("Hello"); // results in the first method being called.
Run Code Online (Sandbox Code Playgroud)

这将取代以下......

string s = "Hello";

switch(s)
{
   case "Hello":
   ...
   break;
   case "Goodbye":
   ...
   break;
   default;
   break;
}
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?从理论上讲,我认为你可以完全取消'if/switch'语句,只调用基于表达式值自动绑定的方法.

c# methods polymorphism dynamic-dispatch

3
推荐指数
1
解决办法
1464
查看次数

什么时候需要动态多态(与静态多态相比)?

我来自函数式语言(例如 Haskell),我非常喜欢使用类型类来实现多态,这也是实现临时重载的结构方法。

然而,最近我开始理解OOP对实际问题进行建模的方式,我很好奇为什么我们需要OOP 语言(例如 Java)中的动态多态性。根据我的经验,大多数函数调用可以在编译时解决,因为许多函数式语言不支持子类型

所以我的问题是,在什么样的情况下我们必须使用动态多态而不是编译时多态?我的猜测是:

  • 当我们使用拥有对象的子类型系统时,我们无法确定它的实际类型(例如,我们有一个包含许多不同类型对象的容器。但是,在这种情况下,为什么不尝试使用代数数据类型联合类型来对容器的元素类型进行建模? ?)。
  • 我们只有对象,我们不知道它的方法的真实名称,所以我们必须使用vptr表来帮助我们。

java oop polymorphism functional-programming dynamic-dispatch

3
推荐指数
1
解决办法
159
查看次数

Common Lisp 对象系统中的通用调度与经典 OOP 中的动态调度相同吗?

我正在阅读Sonja Keene 的《Common Lisp 中的面向对象编程》一书。

在第 2 章中,作者说:

确定调用哪些方法然后调用它们的过程称为泛型调度。每当调用通用函数时,它都会自动发生。

这让我想起了 Dynamic Dispatch 定义(根据Wikipedia):

动态分派是选择在运行时调用多态操作的哪个实现的过程。它通常用于面向对象的编程语言和系统,并被认为是面向对象的编程语言和系统的主要特征。

不幸的是,维基百科目前具备有关条目的通用调度。

因此,我想问:

1 - 动态调度和通用调度基本上是一回事吗?有哪些相似之处?

2 - 有什么区别?由于 CLOS 的灵活性,动态调度是否是通用调度的某种子集?

oop common-lisp dynamic-dispatch clos

3
推荐指数
2
解决办法
86
查看次数

PerformSelector的延迟时间为0?

可能重复:
-performSelector:withObject:afterDelay:work?

在调用长时间运行的方法之前,我经常使用此代码让UI完成其业务:

[obj performSelector:@selector(go) withObject:nil afterDelay:0];
Run Code Online (Sandbox Code Playgroud)

但是它做了什么?

我个人的解释一直go是在下一个运行循环中调用该方法,但肯定是不对的.

objective-c dynamic-dispatch ios

2
推荐指数
1
解决办法
1413
查看次数

究竟为什么编译器在运行之前不能确定变量的真实类型?

我经常听说编译器在某些条件下无法确定要使用的方法的确切实现.Fox的例子,我们可以想象一个场景(所以人们说),对于一个带有方法foo()的父类,在子类中已被覆盖,编译器现在不会调用foo()的哪个实现直到运行时调用.因此,我们有动态调度,vtables等概念.

我的问题是,为什么编译器无法确定要调用的确切实现?我最近停下来想一想,我一直在努力证明这一点.也许有一些非常明显的东西我想念(当我听到答案时,我可能会踢自己).这只是外部环境吗?如果是这样,那将如何发挥出来?

这是一个依赖于语言的限制还是有更基本的东西?

c++ compiler-construction types runtime dynamic-dispatch

2
推荐指数
1
解决办法
126
查看次数

C++动态调度机制及调用正确函数的过程

我了解 vptr 和 vtable 的概念以及它们在实现此机制中的作用。

编译器使用至少一个虚函数为每个类构造一个 vtable 并为每个类实例添加一个 vptr 指针,以便它可以访问 vtable 并在运行时执行正确的函数,但我无法理解具体如何。

考虑以下代码:

struct A
{
  virtual void foo() { cout << "A::foo" << endl; }
  virtual void goo() { cout << "A::goo" << endl; }
};

struct B
{
  virtual void goo() { cout << "B::goo" << endl; }
  virtual void foo() { cout << "B::foo" << endl; }
};

int main()
{
  A *r = (A *)(new B());
  r->foo();
}
Run Code Online (Sandbox Code Playgroud)

输出:

B::goo

你能解释一下 B::goo 是如何以及为什么被执行的吗?编译器是否在编译时确定了要在 vtable 中查找的位置?谢谢。

编辑: …

c++ dynamic-dispatch function-invocation

2
推荐指数
1
解决办法
59
查看次数

Result&lt;(), Box&lt;(dyn SomeTrait + 'static)&gt;&gt; 不满足 Trait Bound

use once_cell::sync::OnceCell;

pub trait SomeTrait {}
pub struct Impl1 {}

impl SomeTrait for Impl1 {}

pub static GLOBAL_THING: OnceCell<Box<dyn SomeTrait>> = OnceCell::new();

pub fn main() {
    GLOBAL_THING.set(Box::new(Impl1 {})).unwrap();
}
Run Code Online (Sandbox Code Playgroud)

我收到此错误,但不知道如何解释它的含义或修复它。

error[E0599]: the method `unwrap` exists for enum `Result<(), Box<(dyn SomeTrait + 'static)>>`, but its trait bounds were not satisfied
   --> src/main.rs:11:42
    |
11  |       GLOBAL_THING.set(Box::new(Impl1 {})).unwrap();
    |                                            ^^^^^^ method cannot be called on `Result<(), Box<(dyn SomeTrait + 'static)>>` due to unsatisfied trait bounds
    |
    = note: the following trait bounds …
Run Code Online (Sandbox Code Playgroud)

abstraction traits dynamic-dispatch rust

2
推荐指数
1
解决办法
1212
查看次数

为什么 Rust 异步迫使实现者对“Waker”使用动态调度

我正在阅读有关如何在 Rust 中实现async/await 的内容,我注意到它RawWaker本质上是一个胖指针。我不太明白为什么Waker本质上是这样实现的struct Waker{data: *const (), vtable: *const WakerVTable},而不是让编译器在编译时知道、和的Waker<T: Wakes>{raw_walker: &mut T}实现。wake()wake_ref()drop()clone()

traits dynamic-dispatch rust async-await

2
推荐指数
1
解决办法
342
查看次数

为什么虚拟成员函数会影响实际上不需要虚拟调度的 TU 的编译代码?

在这样的 TU 中

\n
#include "Foo.hpp"\nint main() {\n    // stuff\n    Foo* foo{new Foo{}};\n    foo->foo();\n    // stuff\n}\n
Run Code Online (Sandbox Code Playgroud)\n

其中Foo.hpp包含

\n
#pragma once\nstruct Foo {\n    virtual void foo(); // implmented somewhere\n};\n
Run Code Online (Sandbox Code Playgroud)\n

除了调用之外不会Foo::foo发生任何事情,对吗?fooisvirtual并且 it 也不是类 are final,所以是的,在另一个TU 中可能存在派生类的对象,等等,但是......就这个 TU 而言,我认为调用override foo是非常清楚的。我不明白事情会怎样。foo->foo()Foo::foo()

\n

那为什么生成的程序集是这样的呢?

\n
main:                                   # @main\n        push    rax\n        mov     edi, 8\n        call    operator new(unsigned long)@PLT\n        mov     rcx, qword ptr [rip + vtable for Foo@GOTPCREL]\n        add     rcx, …
Run Code Online (Sandbox Code Playgroud)

c++ inheritance virtual-functions dynamic-dispatch virtual-table

2
推荐指数
1
解决办法
84
查看次数