爲什麼重寫在運行時解決,而重載在編譯時解決?
是否有任何理由,重寫不能在編譯時解決。C++重載和重寫解析時間
回答
是否有任何理由,重寫不能在編譯時解決。
假設你正在談論的多態性,即
#include <iostream>
class Base
{
public:
virtual void Foo()
{
std::cout << "Base::Foo()" << std::endl;
}
};
class Derived : public Base
{
public:
virtual void Foo()
{
std::cout << "Derived::Foo()" << std::endl;
}
};
上面的代碼允許這樣的事情,以達到預期效果:
void CallFoo(Base& b)
{
b.Foo();
}
int main()
{
Base b;
Derived d;
CallFoo(b); // calls Base::Foo()
CallFoo(d); // Calls Derived::Foo();
}
重要的是要認識到,CallFoo()
什麼都不知道是很重要的關於b
究竟是什麼(它可能指的是Base
實例或Derived
實例)。所有CallFoo()
gets都是對Base
的引用,它沒有提及它實際引用的內容,所以編譯器無法知道它在編譯CallFoo()
時是什麼。因此,確定是應該調用Base::Foo()
還是Derived::Foo()
必然是運行時決策。
卸下virtual
關鍵字(禁用壓倒一切的)將導致上述代碼以打印出Base::Foo()
兩次,不Base::Foo()
然後Derived::Foo()
。這是因爲如果沒有關鍵字virtual
,編譯器會在編譯時簡單地將調用解析爲Base::Foo()
。這就是說,由於虛函數會產生一些開銷(畢竟,需要調用的正確函數是運行時決策),編譯器會盡力找出b
的實際類型CallFoo()
,如果可以的話。在這種情況下,它將成爲編譯時決定。但是,它是一個實現細節。
覆蓋僅在虛擬功能的運行時被解決,因爲這就是dynamic binding的實現方式。非虛函數調用在編譯時解析。
爲什麼重寫是在運行時解決的,而重載是在編譯時解決的?
它實際上取決於。
通常,編譯器無法確定在overidding情況下直接調用的實際函數。這是因爲基類指針可能不知道的實際對象直到運行時。在這種情況下,編譯器無法在運行時解析實際的函數調用。
但是,有時候編譯器可以巧妙地檢測到即使在overidding的情況下也需要調用的函數,並且在這種情況下它們可以解析在編譯時調用的函數。
在重載的情況下,被調用的實際函數可以由編譯器根據傳遞給函數的參數來確定,所以編譯器不需要等到運行時解析這樣的調用,因爲所有的參數類型都是在編譯時已知,因爲C++是一種靜態類型語言,編譯時必須知道所有類型。
'有時編譯器可以巧妙地和確定地檢測到即使在overidding的情況下也需要調用的函數。您是否有這樣的例子? – 2012-03-29 03:19:35
@Jesse:Check out:[什麼時候編譯器靜態地綁定一個虛擬函數調用?](http://stackoverflow.com/questions/7291596/when-can-the-compiler-statically-bind-a-call對一個虛函數),是的我所引用的是一個非常成熟的事實。這裏沒有任何猜測。 – 2012-03-29 03:30:35
感謝您的鏈接! – 2012-03-29 03:46:20
C++中的函數重載可以由編譯器自己處理。在函數重載期間,編譯器「裝飾」函數名稱,技術上稱爲name mangling
。所以在生成的代碼中,每個重載的方法都會有一個單獨的名稱。這樣編譯器知道在編譯時本身調用哪個方法。
在函數重寫(派生類重新定義其基類中的方法)的情況下,如果基類方法是非虛擬的,則在編譯時本身確定要調用的函數。但是如果它是一個虛函數,那麼編譯器無法在編譯時解析調用。虛擬表查找必須通過對象中的虛擬指針發生。這隻會在運行時發生,因爲只有在運行時你纔會知道你正在處理哪個對象。
- 1. 解析Mod重寫
- 2. C++虛擬功能重寫和重載
- 3. C++構造函數重載解析具有多重繼承
- 4. C++重寫/過載問題
- 5. 方法組重載解析如何與方法調用重載解析不同?
- 6. C#解析日期和時間
- 7. C#時間跨度解析
- 8. 時間戳解析在C#
- 9. 重載的方法組參數會混淆重載解析嗎?
- 10. 通過C#解析/重構C#代碼
- 11. 重寫PowerShell參數的解析模式?
- 12. 解析之前重寫solr查詢
- 13. Java重寫和重載在編譯時拋出錯誤?
- 14. 在C++中同時覆蓋和重載
- 15. C++和虛方法重寫
- 16. 夫特3閉合重載解析
- 17. 解析日期和時間
- 18. URL重定向和重寫同時
- 19. Isapi重寫301重定向解析爲404 - 循環引用?
- 20. 錯誤:聲明無法解析重載函數的地址C++
- 21. 無法解析已被C#覆蓋並重載的F#方法。
- 22. 是否有可能重載C#動態類型屬性解析?
- 23. find_if in set in C++:無法解析的重載函數類型
- 24. 語句無法解析重載函數的地址的Qt/C++
- 25. C++模板函數重載解析錯誤
- 26. C++標準,重載函數解析/匹配
- 27. C++ - <無法解析的重載函數類型>
- 28. C++ <未解析的重載函數類型>
- 29. STL和C++中的重載
- 30. C++重寫力
你告訴我們 - 在編譯時如何解決_could_ overriding問題? – ildjarn 2012-03-29 03:30:30
@ildjarn:你可能想檢查我的答案下的評論鏈接。 – 2012-03-29 03:56:05
@Als:動態多態性完全是_disabled_(因此與問題/對話無關)的上下文不是我所問的。顯然,爲了使用多態性,必須處於多態環境中。 – ildjarn 2012-03-29 04:40:44