2011-07-24 48 views
5

在創建程序,編譯器,鏈接器等過程中,函數和操作符重載是否被覆蓋?功能重寫在哪裏完成?

我特別感興趣的是它在C++,Ruby和Python中完成。

回答

4

函數重載是(至少在C++中)在編譯器內部處理。這個想法是,編譯器最終生成的代碼將被硬編碼以調用相應的函數,就好像這些函數都具有不同的名稱,並且您調用了唯一適合參數的函數。更一般地說,在大多數支持重載的編譯語言中,重載解析在編譯時完成,並且發出的代碼將始終調用指示的函數。例如,Haskell支持這種編譯時重載。

運算符重載是一般重載的特例,所以它通常以相同的方式處理。

功能首要幾乎總是在運行時解決,因爲編譯器不能總是告訴這些功能會(中出現的OOP當一個派生類從基類繼承和重新定義其方法之一的術語)在不知道運行時的類型的情況下被調用。有些編譯器可能能夠靜態地證明某個對象具有特定的類型,然後可以優化動態調度,但在所有情況下都無法做到這一點。

我不知道任何支持重載的動態語言,因爲理論上你可以在程序運行時引入新的過載候選項。如果存在這樣的語言,我很樂意開悟。

+0

這取決於你的意思是「重寫」。 AIUI,一個非虛函數可以被覆蓋,但調用的函數是在編譯時確定的。你也可以做一些有趣的事情,比如'virtual void operator()();'...... –

+0

@ tc- C++中的非虛函數可以是**重載**而不是**重載**。試圖覆蓋非虛函數只是在派生類中引入了重載。 – templatetypedef

+3

@tc .:不。非虛函數是隱藏的,沒有被覆蓋。 –

3

對於C++,運算符重載是在編譯器級別完成的,但通過名稱修改過程爲每個函數創建唯一的名稱標識,以便鏈接程序不會抱怨重複的函數定義。在C++中,操作符重載是可能的,因爲可重載操作如+,-,*等是實際函數本身,其前綴爲operator,後面跟着該操作的符號。因此,例如,一個重載operator+功能與像

函數簽名
my_type operator+(const my_type& lhs, const my_type& rhs); 

不會與不同的簽名另一operator+功能發生衝突,即使這兩個函數具有相同的operator+名字,因爲該功能的每個版本都會有C++編譯器的名稱修改過程完成後,在彙編語言級別使用不同的名稱。 Name-mangling的另一個好處是允許C和C++編譯的代碼與相同的鏈接器一起使用,因爲具有相同名稱的兩個函數將不存在並導致鏈接器錯誤。

請注意,在C中,即使您創建兩個具有不同簽名的函數,但如果它們具有相同的名稱,由於C編譯器不會執行任何名稱修改,鏈接器會抱怨函數的重複定義。

+0

Downvoter:這個答案有什麼問題?這似乎是完全合理的。 – templatetypedef

+0

@templatetypedef我認爲這是因爲問題是關於覆蓋和*運算符*重載,而不是在一般情況下重載。 –

+0

好吧,我已經編輯,以使其特定於操作員overaloading ...它仍然是一樣的過程作爲功能重載雖然... – Jason

0

Python沒有鏈接/編譯,它被解釋。 因此,正常的重寫是在分析類源時完成的。當然,由於動態性質,您也可以在運行時重寫。 我想使用byto-code編譯的替代實現可以在編譯時進行。

我也認爲上述對於Ruby也是如此。