下面的代码是否使用动态分派,因为它在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) 长开关的声明往往令人不悦.解决方案是使用多态.但是,如果我正在打开的东西不是类型代码呢?我想做的是用这样的东西替换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'语句,只调用基于表达式值自动绑定的方法.
我来自函数式语言(例如 Haskell),我非常喜欢使用类型类来实现多态,这也是实现临时重载的结构方法。
然而,最近我开始理解OOP对实际问题进行建模的方式,我很好奇为什么我们需要OOP 语言(例如 Java)中的动态多态性。根据我的经验,大多数函数调用可以在编译时解决,因为许多函数式语言不支持子类型。
所以我的问题是,在什么样的情况下我们必须使用动态多态而不是编译时多态?我的猜测是:
java oop polymorphism functional-programming dynamic-dispatch
我正在阅读Sonja Keene 的《Common Lisp 中的面向对象编程》一书。
在第 2 章中,作者说:
确定调用哪些方法然后调用它们的过程称为泛型调度。每当调用通用函数时,它都会自动发生。
这让我想起了 Dynamic Dispatch 定义(根据Wikipedia):
动态分派是选择在运行时调用多态操作的哪个实现的过程。它通常用于面向对象的编程语言和系统,并被认为是面向对象的编程语言和系统的主要特征。
不幸的是,维基百科目前不具备有关条目的通用调度。
因此,我想问:
1 - 动态调度和通用调度基本上是一回事吗?有哪些相似之处?
2 - 有什么区别?由于 CLOS 的灵活性,动态调度是否是通用调度的某种子集?
在调用长时间运行的方法之前,我经常使用此代码让UI完成其业务:
[obj performSelector:@selector(go) withObject:nil afterDelay:0];
Run Code Online (Sandbox Code Playgroud)
但是它做了什么?
我个人的解释一直go是在下一个运行循环中调用该方法,但肯定是不对的.
我经常听说编译器在某些条件下无法确定要使用的方法的确切实现.Fox的例子,我们可以想象一个场景(所以人们说),对于一个带有方法foo()的父类,在子类中已被覆盖,编译器现在不会调用foo()的哪个实现直到运行时调用.因此,我们有动态调度,vtables等概念.
我的问题是,为什么编译器无法确定要调用的确切实现?我最近停下来想一想,我一直在努力证明这一点.也许有一些非常明显的东西我想念(当我听到答案时,我可能会踢自己).这只是外部环境吗?如果是这样,那将如何发挥出来?
这是一个依赖于语言的限制还是有更基本的东西?
我了解 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 中查找的位置?谢谢。
编辑: …
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) 我正在阅读有关如何在 Rust 中实现async/await 的内容,我注意到它RawWaker本质上是一个胖指针。我不太明白为什么Waker本质上是这样实现的struct Waker{data: *const (), vtable: *const WakerVTable},而不是让编译器在编译时知道、和的Waker<T: Wakes>{raw_walker: &mut T}实现。wake()wake_ref()drop()clone()
在这样的 TU 中
\n#include "Foo.hpp"\nint main() {\n // stuff\n Foo* foo{new Foo{}};\n foo->foo();\n // stuff\n}\nRun Code Online (Sandbox Code Playgroud)\n其中Foo.hpp包含
#pragma once\nstruct Foo {\n virtual void foo(); // implmented somewhere\n};\nRun Code Online (Sandbox Code Playgroud)\n除了调用之外不会Foo::foo发生任何事情,对吗?fooisvirtual并且 it 也不是类 are final,所以是的,在另一个TU 中可能存在派生类的对象,等等,但是......就这个 TU 而言,我认为调用override foo是非常清楚的。我不明白事情会怎样。foo->foo()Foo::foo()
那为什么生成的程序集是这样的呢?
\nmain: # @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
dynamic-dispatch ×10
c++ ×3
oop ×2
polymorphism ×2
rust ×2
traits ×2
abstraction ×1
async-await ×1
c# ×1
clos ×1
common-lisp ×1
haskell ×1
inheritance ×1
ios ×1
java ×1
methods ×1
objective-c ×1
runtime ×1
types ×1