c#中虛函數的相關使用方法

來源:互聯網
上載者:User

若一個執行個體方法聲明前帶有virtual關鍵字,那麼這個方法就是虛方法。

虛方法與非虛方法的最大不同是,虛方法的實現可以由衍生類別所取代,這種取代是通過方法的重寫實現的(以後再講)
虛方法的特點:
虛方法前不允許有static,abstract,或override修飾符
虛方法不能是私人的,因此不能使用private修飾符
虛方法的執行:
我們知道一般函數在編譯時間就靜態地編譯到了執行檔案中,其相對位址在程式運行期間是不發生變化的,
而虛函數在編譯期間是不被靜態編譯的,它的相對位址是不確定的,它會根據運行時期對象執行個體來動態判斷要調用的函數,
其中那個申明時定義的類叫申明類,那個執行時執行個體化的類叫執行個體類。
如:A a =new B(); 其中A是申明類,B是執行個體類。
1.當調用一個對象的函數時,系統會直接去檢查這個對象申明定義的類,即申明類,看所調用的函數是否為虛函數;
2.如果不是虛函數,那麼它就直接執行該函數。而如果是一個虛函數,那麼這個時候它就不會立刻執行該函數了,而是開始檢查對象的執行個體類。
3.在這個執行個體類裡,他會檢查這個執行個體類的定義中是否有實現該虛函數或者重新實現該虛函數(通過override關鍵字)的方法,
如果有,它就不會再找了,而是馬上執行該執行個體類中實現的虛函數的方法。而如果沒有的話,系統就會不停地往上找執行個體類的父類,
並對父類重複剛才在執行個體類裡的檢查,直到找到第一個重載了該虛函數的父類為止,然後執行該父類裡重載後的函數。
例1:

複製代碼 代碼如下:class A
{
publicvirtualvoid Sum()
{
Console.WriteLine("I am A Class,I am virtual sum().");
}
}
class Program
{
staticvoid Main(string[] args)
{
A a=new A(); // 定義一個a這個A類的對象.這個A就是a的申明類,執行個體化a對象,A是a的執行個體類
a.Sum();
Console.Read();
}
}

執行a.Sum:
1.先檢查申明類A 2.檢查到是sum是虛擬方法 3.轉去檢查執行個體類A,結果是題本身
4.執行執行個體類A中實現Sum的方法 5.輸出結果 I am A Class,I am virtual sum().
例2:

複製代碼 代碼如下:class A
{
publicvirtualvoid Sum()
{
Console.WriteLine("I am A Class,I am virtual sum().");
}
}
class B : A
{
publicoverridevoid Sum() // 重新實現了虛函數
{
Console.WriteLine("I am B Class,I am override sum().");
}

}
class Program
{
staticvoid Main(string[] args)
{
A a=new B(); // 定義一個a這個A類的對象.這個A就是a的申明類,執行個體化a對象,B是a的執行個體類
a.Sum();
Console.Read();
}
}

執行a.Sum:
1.先檢查申明類A 2.檢查到是虛擬方法 3.轉去檢查執行個體類B,有重寫的方法 4.執行執行個體類B中的方法 5.輸出結果 I am B Class,I am override sum().
例3:複製代碼 代碼如下:class A
{
publicvirtualvoid Sum()
{
Console.WriteLine("I am A Class,I am virtual sum().");
}
}
class B : A
{
publicoverridevoid Sum() // 重新實現了虛函數
{
Console.WriteLine("I am B Class,I am override sum().");
}

}
class C : B
{

}
class Program
{
staticvoid Main(string[] args)
{
A a=new C();// 定義一個a這個A類的對象.這個A就是a的申明類,執行個體化a對象,C是a的執行個體類
a.Sum();
Console.Read();
}
}

執行a.Sum:
1.先檢查申明類A 2.檢查到是虛擬方法 3.轉去檢查執行個體類C,無重寫的方法 4.轉去檢查類C的父類B,有重寫的方法
5.執行父類B中的Sum方法 6.輸出結果 I am B Class,I am override sum().
例4:

複製代碼 代碼如下:class A
{
publicvirtualvoid Sum()
{
Console.WriteLine("I am A Class,I am virtual sum().");
}
}
class B : A
{
publicnewvoid Sum() //覆蓋父類裡的同名函數,而不是重新實現
{
Console.WriteLine("I am B Class,I am new sum().");
}

}
class Program
{
staticvoid Main(string[] args)
{
A a=new B();
a.Sum();
Console.Read();
}
}

執行a.Sum:
1.先檢查申明類A 2.檢查到是虛擬方法 3.轉去檢查執行個體類B,無重寫的(這個地方要注意了,雖然B裡有實現Sum(),但沒有使用override關鍵字,所以不會被認為是重寫) 4.轉去檢查類B的父類A,就為本身 5.執行父類A中的Sum方法 6.輸出結果 I am A Class,I am virtual sum().
那麼如果在例4裡,申明的是類B呢?複製代碼 代碼如下:class A
{
publicvirtualvoid Sum()
{
Console.WriteLine("I am A Class,I am virtual sum().");
}
}
class B : A
{
publicnewvoid Sum() //覆蓋父類裡的同名函數,而不是重新實現
{
Console.WriteLine("I am B Class,I am new sum().");
}

}
class Program
{
staticvoid Main(string[] args)
{
B b=new B();
b.Sum();
Console.Read();
}
}

執行B類裡的Sum(),輸出結果I am B Class,I am new sum().
可以使用抽象函數重寫基類中的虛函數嗎?
答案是可以的。

複製代碼 代碼如下:class A
{
publicvirtualvoid PrintFriends()
{
Console.WriteLine("A.PrintFriends()");
}
}
abstractclass B : A
{
public abstract override void PrintFriends(); //使用override 修飾符,表示抽象重寫了基類中該函數的實現
}
abstract class C : A
{
public abstract new void PrintFriends(); //使用 new 修飾符顯式聲明,表示隱藏了基類中該函數的實現
}

密封類可以有虛函數嗎?
可以,基類中的虛函數將隱式的轉化為非虛函數,但密封類本身不能再增加新的虛函數

複製代碼 代碼如下:class A
{
publicvirtualvoid Fun()
{
Console.WriteLine("I am A.");
}
}
sealedclass Program:A
{
public override void Fun()
{
Console.WriteLine("I am B.");
}
staticvoid Main(string[] args)
{
Program p =new Program();
p.Fun();
Console.Read();
}
}
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.