虚函数和多态
父類中定義的虛函數(shù)
子類對象調用該函數(shù)的同名函數(shù)時,有三種:
(1)子類不定義同名函數(shù),那么子類對象在調用此函數(shù)時,是調用了父類的該函數(shù),即進入父類該函數(shù)的入口地址
(2)子類對象重寫此函數(shù)(new或者override),那么子類對象在調用此函數(shù)時,是調用了子類自己的函數(shù),至于父類該函數(shù)的入口地址是否還存在,之后討論
(3)子類定義一個同名函數(shù),那么子類對象在調用此函數(shù)時,是調用了子類自己的函數(shù),隱藏父類該函數(shù)的入口地址(仍存在),這種情況跟new重寫是一樣的,換句話說new加和不加是沒有影響的
那么對于第(2)種,new和override是有區(qū)別的,new是在父類函數(shù)的入口地址之外再創(chuàng)建一個同名函數(shù)入口地址,而override是把父類函數(shù)的入口地址覆蓋了。
具體看我在vs2008中調試的例子代碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
??? class A
??? {
??????? public virtual void Get()
??????? {
??????????? Console.WriteLine("父類A函數(shù)");
??????? }
??? }
??? class B:A
??? {
??????? public new void Get()
??????? {
??????????? Console.WriteLine("子類B函數(shù)");
??????? }
??? }
??? class C : A
??? {
??????? public override void Get()
??????? {
??????????? Console.WriteLine("子類C函數(shù)");
??????? }
??? }
??? class D : A
??? {
??????? public void Get()
??????? {
??????????? Console.WriteLine("子類D函數(shù)");
??????? }
??? }
??? class Program
??? {
??????? static void Main(string[] args)
??????? {
??????????? /************
??????????? //父類對象調用父類方法
??????????? A a = new A();
??????????? a.Get();
??????????? Console.ReadLine();
??????????? //子類對象調用子類(new)方法
??????????? B b = new B();
??????????? b.Get();
??????????? Console.ReadLine();
??????????? //子類對象調用子類(override)方法
??????????? C c = new C();
??????????? c.Get();
??????????? Console.ReadLine();
??????????? //子類對象調用子類方法
??????????? D d = new D();
??????????? d.Get();
??????????? Console.WriteLine();
???????????? * /
??????????? /***************
??????????? //父類對象試圖調用子類方法,需要將子類對象轉化為父類對象,b調用的是父類的函數(shù),c調用的是子類的函數(shù)。
??????????? //因為關鍵字new實現(xiàn)重寫是再創(chuàng)建了一個函數(shù)入口地址,也就是說這時子類對象同時保存了父類該函數(shù)的入口地址和子類該函數(shù)的入口地址,
??????????? //只是父類該函數(shù)的入口地址被隱藏,但仍可用,當父類對象去調用去調用子類方法時,子類會提供父類對象該函數(shù)的入口地址。這樣就實現(xiàn)了根據(jù)對象類型自動選擇函數(shù)入口地址。(其實這里new加和不加效果是一樣的)
??????????? //而關鍵字override實現(xiàn)重寫是用子類創(chuàng)建的該函數(shù)入口地址覆蓋父類該函數(shù)的入口地址,這樣一來,子類對象只保存了子類該函數(shù)的入口地址。
??????????? a = b;
??????????? a.Get();
??????????? Console.WriteLine();
??????????? a = c;
??????????? a.Get();
??????????? Console.WriteLine();
??????????? a = d;
??????????? a.Get();
??????????? Console.WriteLine();
??????????? */
??????????? /***************
??????????? //子類對象試圖調用父類方法,需要將父類對象轉化為子類對象。父類對象可以強制轉換為子類對象,但是前提是此父類對象為子類實例化的結果。
??????????? //“父類對象為子類實例化的結果”與“父子類各自實例化一個對象后,將子類對象轉化為父類對象”這兩種情況都能實現(xiàn)
??????????? A a = new B();
??????????? a.Get();
??????????? Console.ReadLine();
??????????? ((B)a).Get();
??????????? ((A)a).Get();
??????????? a = new C();
??????????? a.Get();
??????????? Console.ReadLine(); ?
???????????? * /
??????? }
??? }
}
用override可以實現(xiàn)多態(tài),用new可以實現(xiàn)更漂亮的多態(tài),可以參考這篇文章http://www.cnblogs.com/kimma/archive/2008/09/07/1285857.html
?
總結虛函數(shù)作用,純虛函數(shù)就是強制子類有同樣的成員函數(shù)接口,虛函數(shù)就是強制子類有同樣的成員函數(shù)接口以及接口默認實現(xiàn)。一個類中最好不要完全沒有虛函數(shù)也不要全是虛函數(shù),這都是設計不合理。總的來說,虛函數(shù)實現(xiàn)多態(tài)。
轉載于:https://www.cnblogs.com/webclient/archive/2012/06/11/2545483.html
總結
- 上一篇: (转)Facebook如何提高软件质量?
- 下一篇: Curl参数一览