c++ - "Direct"与 "virtual"调用虚函数

标签 c++ terminology virtual-functions

我是自学成才的,因此不熟悉很多术语。我似乎无法通过谷歌搜索找到答案:What is a "virtual"vs a "direct"call to a virtual function?

这属于术语,而不是技术细节。我问的是何时将调用定义为“直接”与“虚拟”进行的调用。 它不涉及虚表,也不涉及与这些概念的实现有关的任何其他内容。

最佳答案

您问题的答案在不同的概念层面是不同的。

  • 在概念语言层面,非正式术语“虚拟调用”通常是指根据调用中使用的对象的动态类型 解析的调用。根据 C++ 语言标准,这适用于对虚函数的所有调用,使用函数的限定名称 的调用除外。当在调用中使用方法的限定名称时,该调用称为“直接调用”

    SomeObject obj;
    SomeObject *pobj = &obj;
    SomeObject &robj = obj;
    
    obj.some_virtual_function(); // Virtual call
    pobj->some_virtual_function(); // Virtual call
    robj.some_virtual_function(); // Virtual call
    
    obj.SomeObject::some_virtual_function(); // Direct call
    pobj->SomeObject::some_virtual_function(); // Direct call
    robj.SomeObject::some_virtual_function(); // Direct call
    

    请注意,您经常会听到人们说通过直接对象 对虚函数的调用“不是虚函数”。然而,语言规范并不支持这种观点。根据该语言,所有对虚函数的非限定调用都是相同的:它们根据对象的动态类型 进行解析。在那种[概念]意义上,它们都是虚拟的

  • 在实现级别,术语“虚拟调用”通常是指通过某种实现定义的机制分派(dispatch)的调用,该机制实现虚拟函数的标准要求功能。通常它是通过与调用中使用的对象关联的虚拟方法表 (VMT) 实现的。然而,聪明的编译器只会在真正需要时才使用 VMT 来执行对虚函数的调用,即当对象的动态类型在编译时未知时。在所有其他情况下,编译器将努力直接调用该方法,即使调用在概念级别上是正式的“虚拟”。

    例如,大多数时候,使用直接对象(而不是指针或对象引用)对虚函数的调用将作为直接调用实现(不涉及 VMT 调度).这同样适用于从对象的构造函数和析构函数中立即调用虚函数

    SomeObject obj;
    SomeObject *pobj = &obj;
    SomeObject &robj = obj;
    
    obj.some_virtual_function(); // Direct call
    pobj->some_virtual_function(); // Virtual call in general case
    robj.some_virtual_function(); // Virtual call in general case
    
    obj.SomeObject::some_virtual_function(); // Direct call
    pobj->SomeObject::some_virtual_function(); // Direct call
    robj.SomeObject::some_virtual_function(); // Direct call
    

    当然,在后一种意义上,如果编译器有足够的信息来确定动态类型,则没有什么可以阻止编译器将对虚函数的任何调用实现为直接调用(不涉及 VMT 调度)对象在编译时。在上面的简单示例中,任何现代编译器都应该能够将所有调用实现为直接调用。

关于c++ - "Direct"与 "virtual"调用虚函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36584670/

相关文章:

c++ - 纯虚函数问题

operating-system - 虚拟内存耗尽时会发生什么

c++ - 什么是 "modf()"(来自 C/C++ 等的数学函数)的简写?

c++ - 如何将 C++ 目标文件链接到 C 可执行文件?

c++ - 如何在Visual Studio 2008中隐藏这两个控件?

c++ - 在双链表数据结构类实验室项目中实现append和insertAt函数

c - 全局变量的乘法声明/定义

hash - 哈希值和 MAC(消息验证码)有什么区别?

c++ - CRTP 能否完全替代较小设计的虚拟功能?

c++ - std::对象的 move 和构造/销毁