机器码层虚函数和条件执行的区别

Difference Between Virtual Function and Conditional Execution on Machine Code Layer

我正在尝试理解虚函数的概念。根据Wikipedia:

In short, a virtual function defines a target function to be executed, but the target might not be known at compile time.

我的问题是,这与条件执行有何不同?

void conditional_func(func_to_run) {
    switch(func_to_run) {
        case func1_tag: func1(); break;
        case func1_tag: func1(); break;
        ...
    }
}

int main() {
    read func_to_run
    conditional_func(func_to_run)
}

如您所见,conditional_func 的最终目标在 运行 时未知。

在 C++ 中,虚函数似乎被定义为允许 "polymorphism" 的工具。我对多态性的定义:多态性 class 是 class 对象可以具有不同的形式(形态学),而不是具有静态形式。也就是说,对象可以根据它们的 subclass. 具有不同的操作和属性(我在定义中避免提及特定于语言的概念,如指针)

因此在 C++ 中所谓的虚函数甚至不必依赖于动态绑定(运行目标函数的时间分辨率),而是可以在编译时有一个已知的目标:

int main()
{
    Drived d;
    Base *bPtr = &d;
    bPtr->func();
}

在上面的例子中,编译器知道Base指针指向一个Derived对象,因此会知道运行版本的func的目标地址。因此我的结论是,维基百科所指的虚函数与出于某种原因动态绑定的 C++ 虚函数相同:

int main()
{
    Drived1 d1;
    Drived2 d2;
    read val;
    if (val == 1) Base *bPtr = &d1;
    else Base *bPtr = &d2;
    bPtr->func();
}

如您所见,这也只是条件执行。所以这是我的问题:

1) 如果在编译时将虚函数定义为目标未知的函数,这与条件执行有何不同?它们在汇编级别上相同但在更高的抽象层上不同吗?

2) 如果将虚函数定义为允许如上定义的多态性的工具,那么是否再次意味着它只是高级语言的概念?

1) If virtual function is defined as a function with unknown target at compile time, how is this different than conditional execution? Are they the same in assembly level but different at higher layers of abstraction?

在 assembly/machine 代码级别,虚拟函数通常实现为 class 特定的 table 函数指针(称为虚拟调度表或 VDT),每个对象这些类型中有一个指向其 class 的 table 的指针。这些 tables 的布局在基础和派生 classes 之间是一致的,因此给定一个指向层次结构中任何对象的指针,任何给定虚函数的函数指针总是在所有的相同位置classes 的 VDT。这意味着相同的机器代码可以获取对象指针并找到要调用的函数。

与您说明的基于开关的代码类型的不同之处在于,所有具有此类开关的代码都需要手动更新和重新编译以支持更多类型。使用函数指针,新类型的新代码可以简单地链接到通过指针工作的现有代码,而无需更改或重新编译后者。

2) If virtual function is defined as a facility to allow for polymorphism as defined above, then does it mean that again it is only a concept of higher level languages?

首先,您定义多态性的尝试与 C++ 术语不一致。你有:

A polymorphic class is a class with objects that can have different forms (morphology) as opposed to having a static form. That is, the objects can have different actions and properties based on their subclass.

在 C++ 中说任何给定的 class 都有一种形式会更接近事实,并且在继承层次结构中它是不同的 classes 可能有不同的形式/动作 /属性。

以后。在机器代码级别,您可以 - 显然考虑到 C++ 必须输出机器代码 - 使用函数指针并获得与虚函数相同的运行时效果。

虚函数增加的是让编译器为您完成大部分工作的便利性和可靠性:

  • 创建虚拟调度 tables,
  • 确保函数指针的顺序一致,
  • 为对象提供指向这些 table 的隐式指针,并在第一个非抽象基础的构造函数中可靠地初始化它,并随着构造在 class 层次结构中向下冒泡到实际对象的运行时而更新它类型,然后在析构函数启动时反转指针的值,
  • 检查覆盖是否与它们覆盖的虚函数具有相同的函数签名,
  • 当被调用的函数可以在编译时推导出来时,可选地优化运行时分派。

这样的保证和编译器生成的操作使得 C++ 风格的虚函数和分派比程序员协调使用函数指针更高级的语言功能,更不用说运行时类型的切换了。也就是说,没有什么可以特别阻止某人向汇编语言添加此类支持。也就是说,许多总体上比 C++ 级别更高的语言缺少与虚函数类似的东西。 (在极端情况下,5GL 甚至可能不会向 "programmer"/用户公开函数的概念。