使用關鍵字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