使用关键字virtual时,如果compliler-linker知道调用者和被调用者的位置(地址/偏移量保存在表中等),那么所有地址都可以在exe中被硬编码。那么它不应该被称为早期绑定。如果仅在执行调用者代码(操作系统中的地址?)时获得地址,则这必须是真正的后期绑定。如果后期绑定是首选,为什么编译器 - 链接器不想使用它(不管源代码是否使用了虚拟关键字)?萨姆早期和晚期绑定是如何实现的?
回答
考虑这个例子:
#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在评论中指出的那样,虚拟方法可以防止内联。这可能会对性能产生显着影响(与通话开销不同,后者几乎从不会被注意到)。
关于虚拟通话费用:与常规通话相比,虚拟通话本身通常并不昂贵(只要对分支预测器而言“容易”),通常很大的成本就是错失了内联机会。我不得不在内部循环中删除虚拟呼叫,在某些情况下可以获得2倍或更多的加速。 –
如果在呼叫者代码被执行仅获得地址(从操作系统地址?)
它不来自于操作系统,但是从(有效)的函数的指针。
那么这必须是真正的晚期绑定。
它是。
如果后期绑定是首选,为什么编译器,链接器并不一定要使用它(不考虑如果源代码中使用的虚拟关键字,或者不是)?
那么,这不是首选。速度非常慢。这不一定是因为“物理”函数调用花费的时间比正常的要长很多;由于额外的间接方法需要更长的时间,但真正的不利之处在于你的调用无法完全消除(通过内联),因为编译器不知道哪个函数最终会在运行时被调用。
除非您需要它,否则您不想使用它,即您需要虚拟呼叫。
这个决定与您在“我应该只是调用一个函数还是应该从一堆选项中查找映射中的函数指针并调用我想要的函数指针那?”您使用正确的工具来完成这项工作,但额外的灵活性会带来成本。
@DavidHaim:是的,这使得它在我的书中“非常慢”:)对内联等等说再见。当然,实际上量化是一件复杂的事情。 –
我会澄清它。 –
- 1. 后期和早期绑定在Ruby中
- 2. 选择的最早和最晚日期
- 3. SQL查询早/晚日期
- 4. 创建早期绑定实体类
- 5. Log Parser早期绑定
- 6. 将早期绑定代码转换为后期绑定
- 7. vb.net反射与晚期绑定?
- 8. Microsoft CRM 2011中PreImage的早期绑定
- 9. JavaScript:检查日期A最早/最晚比日期早3倍B
- 10. jQuery早期绑定函数可能吗?
- 11. 获得一个早期绑定关系
- 12. 早期绑定实体“ActivityPointers”上的XmlSerializer错误
- 13. 如何定义早绑定实体?
- 14. 铸造早期绑定对象类型到后期绑定的对象类型
- 15. 寻找伯爵,最早日期和最晚日期为每名在Python
- 16. 如何早期绑定查询到的IQueryable <TEntity>
- 17. 如何实现早期版本Android的setVideoScalingMode
- 18. 如何实现张量流中的早期停止
- 19. 将早期绑定转换为后期绑定而不更改对象类型
- 20. 将早期绑定VBA转换为后期绑定VBA:Excel到Outlook联系人
- 21. 如何解决此早期绑定失败?
- 22. 如何在早期绑定状态码上为QueryExpression创建ConditionExpression?
- 23. 将UnixTime转换为R中的日期间隔(早上,晚上,晚上等)
- 24. 如何将后期绑定语法转换为vb.net中的早期绑定语法?
- 25. 如何在C语言中实现后期绑定?
- 26. 简单的方法来安排星期几[星期一到星期五]闹钟早上和晚上在android?
- 27. 目标C - 确定哪个日期晚是日期格式
- 28. 对以下方法的调用是否被认为是晚期绑定?
- 29. 早期的ActionScript电影提示点触发太晚
- 30. 哪一个是在性能方面更好,在Delphi COM的早期绑定或后期绑定对象
目前尚不清楚你在说什么。你似乎在混淆C++多态和库链接。这些是不同的事情。 –
'如果compliler-linker知道调用者和被调用者的位置(地址/偏移保存在表中等),那么所有地址都可以在exe中被硬编码 - 如果可以的话。一般情况下它不能。然后它只是一个函数ptr(在表中)。 – lorro