2012-06-06 56 views
13

民間重載是如何編譯時間和覆蓋是運行時?

我遇到了很多理解多態性(編譯時間和運行時間)的線程。我很驚訝地看到一些程序員聲稱Overloading是Runtime和Overriding是編譯時的鏈接。

我想從這裏知道的是:

  1. 運行時多態性與實時例如,小碼和什麼情況下,我們應該使用。
  2. 使用REAL TIME示例和小代碼編譯時間多態性以及何時使用。

因爲我看過很多理論的定義,但我不理解的是滿意的。

另外,我給了一個想法,我也覺得,重載應該是運行時,因爲,比如說我有一個計算Area的方法,在運行時它只能根據參數I pass來決定調用哪個重載方法如果我只傳遞一個參數,它應該觸發Square,如果參數是2,它應該觸發Rectangle)....那麼是不是我可以聲明它的運行時?它的編譯時間如何? (大多數理論上講,過載是編譯時間,但他們甚至沒有給出一個正確的實時時間的例子...很少聲稱它的運行時間)...

此外,我覺得重寫是編譯時,因爲,當你編寫代碼並且complie,你確保你使用了virtual關鍵字,並且在派生類中重寫了這個方法,否則會給你編譯時錯誤。所以我覺得它的編譯時間,以同樣的方式,我在一個線程看到.....但多數線程聲稱其運行時:d

我很困惑:(這個問題是附加到我的問題1和2,請與實時例如幫助..因爲我已經知道的理論定義.... :(

謝謝....

+0

如果我完全理解你的問題:運行時間,調用虛擬方法。編譯時間,調用任何其他方法。 –

+0

UhmmM傑夫,但它是一切嗎? – Learner

回答

11

在重載的情況下,您使用的是靜態(編譯時)多態性,因爲編譯器知道您正在調用哪種方法。例如:

public static class test 
{ 
    static void Main(string[] args) 
    { 
     Foo(); 
     Foo("test"); 
    } 

    public static void Foo() 
    { 
     Console.WriteLine("No message supplied"); 
    } 

    public static void Foo(string message) 
    { 
     Console.WriteLine(message); 
    } 
} 

在這種情況下,編譯器根據參數的數量/類型確切知道我們調用的是哪個Foo()方法。

覆蓋是一個動態(運行時)多態性的例子)。這是由於編譯器不一定知道在編譯時傳入什麼類型的對象。假設你有下面的類在庫:

public static class MessagePrinter 
{ 
    public static void PrintMessage(IMessage message) 
    { 
     Console.WriteLine(message.GetMessage()); 
    } 
} 

public interface IMessage 
{ 
    public string GetMessage(); 
} 

public class XMLMessage : IMessage 
{ 
    public string GetMessage() 
    { 
     return "This is an XML Message"; 
    } 
} 

public class SOAPMessage : IMessage 
{ 
    public string GetMessage() 
    { 
     return "This is a SOAP Message"; 
    } 
} 

在編譯的時候,你不知道,如果函數的調用者傳遞一個XMLMessage之外,SOAPMessage,或可能在其他地方定義的另一種類型的消息對象的。當PrintMessage()函數是呼叫時,它確定在運行時要使用哪個的GetMessage()的版本,基於被傳入消息對象的類型。

+3

喬恩,我應該和你這樣的人一起工作,爲了兩件事情:1.爲了完成任務而爲實時和令人滿意地學習東西,爲了激情而不是編碼並獲得報酬2.你的分享你的知識的態度,最重要的是能夠提問人的思維方式......與MSDN不同...... :(非常感謝Jon,你的榜樣我理解它更大程度上的概念....開心:)乾杯 – Learner

+0

只是爲了避免出現「Foo」的問題:無法在靜態類中聲明實例成員,你的方法必須是靜態的。 – Rahul

+0

我花了一分鐘才明白你的意思,但我看到你指的是你的編輯。感謝您指出我在第一個示例中聲明瞭靜態類中的實例成員。我匆匆把這個例子扔在一起,沒有注意到。 –

3

閱讀:Polymorphism (C# Programming Guide)

類似的答案:Compile Time and run time Polymorphism

那麼,有兩種類型多態性的規定如下:

  • 靜態多態(早期綁定)
  • 動態多態性(後期綁定)

靜態多態(早期綁定):

靜態多態也知道作爲早期綁定和編譯時間多態性。方法重載和運算符重載是相同的例子。

這是被稱爲早期綁定,因爲編譯器知道具有相同名稱的功能也發生過載功能砥稱爲是在編譯時已知。

例如:

public class Test 
{ 
    public Test() 
    { 

    } 

    public int add(int no1, int no2) 
    { 

    } 

    public int add(int no1, int no2, int no3) 

    { 

    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Test tst = new Test(); 
     int sum = tst.add(10, 20); 

     // here in above statement compiler is aware at compile time that need to call function add(int no1, int no2), hence it is called early binding and it is fixed so called static binding. 
    } 
} 

動態多態性(後期綁定):

public class Animal 
{ 
    public virtual void MakeSound() 
    { 
     Console.WriteLine("Animal sound"); 
    } 
} 

public class Dog:Animal 
{ 
    public override void MakeSound() 
    { 
     Console.WriteLine("Dog sound"); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Animal an = new Dog(); 
     an.MakeSound();   
     Console.ReadLine(); 
    } 
} 

如在上述代碼中,如任何其他呼叫到虛擬方法,將被編譯到一個callvirt IL指令。這意味着被調用的實際方法是在運行時確定的(除非JIT可以優化某些特殊情況),但編譯器檢查該方法是否存在,是否選擇了最合適的重載(如果有的話),並且它有保證函數指針將存在於類型的vtable中的一個定義良好的位置(即使這是一個實現細節)。解決虛擬呼叫的過程非常快(您只需要解除引用幾個指針),所以它沒有太大區別。

+0

Pranay謝謝你。但爲什麼只有當我在運行時輸入值時,在你的情況下只說2個參數,它決定用2個參數調用該方法?它只是在編譯時編譯......你怎樣稱它爲編譯時間:(它的運行時間,因爲在運行時只基於輸入,它會觸發相應的功能...... – Learner

+0

@Divine-它的命令時間因爲編譯器知道它必須調用哪個方法,例如,如果2參數在那裏,編譯器很容易檢測到它必須調用2參數方法...如果3比調用gose參數到3參數... –

+0

@ Divine-編譯器知道簽名這樣可以很容易地解決問題...... –

0
public class Animal { 
    public virtual void MakeSound() 
    { 
     Console.WriteLine("Animal sound"); 
    } } 

public class Dog:Animal { 
    public override void MakeSound() 
    { 
     Console.WriteLine("Dog sound"); 
    } } 

class Program { 
    static void Main(string[] args) 
    { 
     Animal an = new Dog(); 
     an.MakeSound();   
     Console.ReadLine(); 
    } } 

這是動態的多態,因爲它是在決定運行時哪個版本的MakeSound將被稱爲父代或子代,因爲子代可能不會覆蓋父代函數或可能覆蓋它,但所有這些都是在運行時決定的,哪個版本被稱爲....