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

时间:2018-04-19 18:47:09

标签: c++ function polymorphism virtual

我试图理解虚函数的概念。根据{{​​3}}:

  

简而言之,虚函数定义了要执行的目标函数,   但目标在编译时可能不知道。

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

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 ++中,似乎虚函数被定义为允许“多态”的工具。我对多态性的定义:多态类是一个具有不同形式(形态)的对象的类,而不是具有静态形式。也就是说,对象可以基于它们的子类具有不同的动作和属性。(我不会在我的定义中提到像指针这样的语言特定概念)<​​/ p>

因此,在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 个答案:

答案 0 :(得分:1)

  

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

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

与您所说明的基于交换机的代码类型的区别在于,所有具有此类交换机的代码都需要手动更新并重新编译以支持更多类型。使用函数指针,新类型的新代码可以简单地链接到通过指针工作的现有代码,而不会更改或重新编译。

  

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

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

  

多态类是一个类,其对象可以具有不同的形式(形态),而不是具有静态形式。也就是说,对象可以根据其子类具有不同的操作和属性。

在C ++中更接近真理,说任何给定的类都有一个表单,并且它在继承层次结构中的不同类可能有不同的表单/动作/属性。

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

虚拟功能添加的是让编译器为您完成大部分工作的便利性和可靠性:

  • 创建虚拟调度表,
  • 确保函数指针的一致排序,
  • 给对象一个隐式指向这些表的指针,并在第一个非抽象基的构造函数中可靠地初始化它,然后将它更新为类继承到实际对象的运行时类型的构造气泡,然后将指针的值反转为析构函数踢进去,
  • 检查覆盖是否与它们覆盖的虚函数具有相同的函数签名,
  • 可选择在编译时推断出被调用函数时优化运行时调度。

这种保证和编译器生成的动作使得C ++风格的虚函数和调度程序员协调使用函数指针的语言特性更高,更不用说切换运行时类型了。也就是说,没有什么特别阻止某人将这种支持添加到汇编语言中。也就是说,许多平衡甚至比C ++更高级的语言缺乏与虚函数类似的东西。 (在极端情况下,5GL甚至可能不会向“程序员”/用户公开函数的概念。