多早& &;实现了后期绑定

How Early & Late bindings are implemented?

本文关键字:绑定 实现 多早      更新时间:2023-10-16

当使用关键字virtual时,如果编译器-链接器知道调用者和被调用者的位置(地址/偏移量被保存在表中等),那么所有地址都可以在exe中硬编码。那么它不应该被称为早期绑定吗?如果只有在执行调用者代码时才获得地址(来自操作系统的地址?),那么这必须是真正的后期绑定。如果延迟绑定是首选,为什么编译器-链接器不想使用它(不管源代码是否使用了virtual关键字)?Saam

如果地址只在调用者代码执行时获得(来自操作系统的地址?)

它不是来自操作系统,而是(有效地)来自函数指针。

,那么这必须是真正的后期绑定。

如果延迟绑定是首选,为什么编译器-链接器不想使用它(不管源代码是否使用了virtual关键字)?

嗯,这不是首选。它要慢得多。这并不一定是因为"物理"函数调用比正常调用花费的时间要长得多;由于额外的间接性,它确实需要更长的时间,但真正的损害是,您的调用不能完全被忽略(通过内联),因为编译器不知道哪个函数将在运行时被调用。

你不希望使用它,除非你需要它,即你需要一个虚拟呼叫。

这个决定和你说"我应该直接调用一个函数,还是我应该从一堆选择中查找一个函数指针,然后像这样调用我想要的那个?"您使用了适合工作的工具,但是额外的灵活性是有代价的。

考虑这个例子:

#include <iostream>
#include <memory>
class Base {
public:
    virtual void foo() = 0;
};
class Derived1: public Base {
public:
    virtual void foo() { std::cout << "impl1" << std::endl; }
};
class Derived2: public Base {
public:
    virtual void foo() { std::cout << "impl2" << std::endl; }
};
int main() {
    int c;
    std::cin >> c;
    std::unique_ptr<Base> inst;
    if (c) inst.reset(new Derived1());
    else inst.reset(new Derived2());
    inst->foo();
}

在这里,在真正运行程序之前,您不知道调用了哪个foo()实现。所以,是的,c++有真正的后期绑定。

延迟绑定的缺点是在调用虚拟方法时有一个很小的开销。由于c++可以在一些超级优化的计算库中使用,所以是否使用它的决定留给程序员。

正如Matteo Italia在评论中指出的那样,虚拟方法阻止了内联。这可能会对性能产生明显的影响(不像调用开销,它几乎永远不会被注意到)。