gpt4 book ai didi

C++:使用指向派生类的指针进行虚函数调用仍然有一个vlookup

转载 作者:可可西里 更新时间:2023-11-01 18:36:54 25 4
gpt4 key购买 nike

只是想知道,如果我有一个指向最派生类的指针,并在其上调用最派生类定义的虚函数,这是否仍然会导致在虚拟表中进行查找?

毕竟在编译时,编译器知道这个类是最派生的,它知道它定义了虚函数,没有歧义,所以它应该把它当作非虚函数吗?

还是我遗漏了什么?

我问的原因是我正在编写一个模板,稍后我想从中派生以合并代码,并且不同的功能将在派生类中实现。

没有必要在模板中将这些函数定义为虚拟函数,但如果虚拟调用稍后会被忽略,我正在考虑这样做,纯粹是为了让实现者稍后看到哪些函数仍需要编写。

最佳答案

免责声明:编译器优化

这个答案是关于编译器优化技术的。您的编译器可能支持也可能不支持这些。即使它支持您尝试利用的技术,它们也可能在您选择的优化级别不可用。

您的里程可能会有所不同。

派生类最多

编译器确实可以将调用去虚拟化如果它知道这确实是最派生的类。讨论了如何实现这一点 here .一个例子:

struct Base { virtual void call_me_virtual() = nullptr; };
struct Derived final : Base { void call_me_virtual() override { } };

void dosomething(Derived* d) {
d->call_me_virtual();
}

有趣的是,如果不这样做,您总是可以让其他人从您的类派生在另一个翻译单元中,因此编译器不会意识到您当前的“更多派生”类翻译单元。

另一种确保类必须是最派生的方法是将其放入匿名命名空间:

struct Base { virtual void call_me_virtual() = nullptr; };

namespace {
struct Derived : Base { void call_me_virtual() override { } };

void dosomething(Derived* d) {
d->call_me_virtual();
}
}

这是有效的,因为 Derived 在当前翻译单元之外是未知的,这意味着任何更多的派生类必须在当前翻译单元内。然而,这意味着 dosomething 不能(正确地)从当前编译单元外部调用,这就是为什么我也给了它内部链接。

此规则的一个豁免是编译器能够证明该对象来自他们的 View ,例如如果 Derived 是当前翻译单元中派生程度最高的类型,并且对象必须始终来自当前翻译单元,那么它不能来自任何更多的派生类型。通过利用整个程序优化可以扩大此分析的范围。

已知类型

更常见的情况是编译器确切地知道对象的类型,例如在这两种情况下:

Derived d;
d.call_me_virtual();

Base* b = new Derived;
b->call_me_virtual();

编译器可能能够推断出 d.call_me_virtualb->call_me_virtual 都将始终解析为 Derived::call_me_virtual 并且因此在该实例中去虚拟化(甚至内联)调用。

在第一种情况下,这需要知道 Derived 类型的对象不同于非常相似的 Derived& 类型的对象只能是 Derived 对象,而不是从中派生的东西。

第二种情况需要静态类型分析,这是由现代优化编译器完成的。通过查看 b 总是 使用指向 Derived 对象的指针进行初始化,编译器能够证明 将调用哪个函数>b->call_me_virtual

完成成员(member)功能

当您完成单个成员函数时,会发生类似的情况:

struct Base { virtual void call_me_virtual() = nullptr; };
struct Derived : Base { void call_me_virtual() override final { } };

void dosomething(Derived* d) {
d->call_me_virtual();
}

虽然 d 可能指向从 Derived 派生的东西,但 call_me_virtual 方法可能不会再更改,所以编译器知道 Derived::call_me_virtual 将始终被调用,因此可以将此调用去虚拟化。

关于C++:使用指向派生类的指针进行虚函数调用仍然有一个vlookup,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23517744/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com