希望這篇文章對理解C#的物件模型有所協助

來源:互聯網
上載者:User
今天看到這篇文章 一個在C#以及類似的物件導向系統(Java中估計也是如此)中常見的錯誤,感觸頗多,說句實在話,國內目前的OO語言教學中忽略了一個關鍵的一環“OO的物件模型”,這裡有本好書:侯捷的《深度探索C++物件模型》。看過的與沒有看過的,對理解OO的物件模型有層次的不同。看過的人往往會思考:“編譯器到底做了什麼”?沒看過的會想當然:“應該是這樣的,就是這樣的......”。比如把一個子類對象強制轉換為基類對象,其實編譯器處理就是把該對象作為基類對象來處理(即對象的Slip)。當然調用的方法(非虛函數)也是基類的方法,和子類無關。而調用虛函數則先要去對象記憶體位址,再擷取對應的vTable(在C++,Delphi中都是類似處理,根據對象的地址,擷取該對象的vTable),再根據虛函數的位移量擷取vtable表中的實際虛函數的函數地址,從而實現OO的多態。

還是通過執行個體代碼來解釋吧public class BaseClass
    {
        public string m_Name = "BaseClass";

        public void RealName()
        {
            Console.WriteLine(m_Name);
        }

        public virtual void VirtualName()
        {
            Console.WriteLine(m_Name);
        }
    }

    public class DerivedClass : BaseClass
    {
        public string m_Name = "DerivedClass";

        public void RealName()
        {
            Console.WriteLine(m_Name);
        }

        public override void VirtualName()
        {
            Console.WriteLine(m_Name);
        }
    }

    public class Class2
    {
        [STAThread]
        static void Main(string[] args)
        {
            BaseClass lBaseclass = new DerivedClass();
            lBaseclass.RealName();//return :  BaseClass 
            lBaseclass.VirtualName();//return :  DerivedClass
            Console.WriteLine("-----------------------");

            DerivedClass lDerivedClass = (DerivedClass)lBaseclass;
            lDerivedClass.RealName();//return :  DerivedClass
            lDerivedClass.VirtualName();//return :  DerivedClass
            Console.WriteLine("-----------------------");

            lBaseclass.m_Name = "ModifyByBase";
            lBaseclass.RealName();//return :  ModifyByBase
            lBaseclass.VirtualName();//return :  DerivedClass
            Console.WriteLine("-----------------------");

            lDerivedClass.m_Name = "ModifyByDerived";
            lDerivedClass.RealName();//return :  ModifyByDerived
            lDerivedClass.VirtualName();//return :  ModifyByDerived
            Console.WriteLine("-----------------------");


            lDerivedClass = new DerivedClass();
            ((BaseClass)lDerivedClass).RealName();//return :  BaseClass
            ((BaseClass)lDerivedClass).VirtualName(); //return :  DerivedClass            

            Console.ReadLine();
        }    

    }

上面第一段代碼的記憶體布局如所述:

第二段的代碼相對簡單,只是把用lBaseClass指向的對象強制類型轉換為子類對象,記憶體結構如所示:

第三段的代碼的記憶體結構如所示:

第四段的代碼的記憶體結構如所示:

第五段的記憶體如所示:

總之,大家要知道,等編譯完成後,所有的屬性訪問或者函數調用都已經根據變數的宣告類型都被確定了(訪問哪個記憶體位址已經確定了),除了虛函數(晚綁定)...。

比如調用lBase.VirtualName()這個虛函數,編譯器做的工作流程如下:
1,為BaseClass和DerivedClass的各個虛函數編號1(位移量)
2,lBase.VirtualName()表示調用lBase對象的vtable指標(在C++,Delphi中都是類似處理,根據對象的地址,擷取該對象的vTable)所指向的vTable表中的1號虛函數。
3,那麼如果lBase實際是指向BaseClass建立的對象,那麼就會調用BaseClass的VirtualName(),如果lBase實際是指向DerivedClass建立的對象,那麼就會調用DerivedClass的VirtualName()。則就是多態。

這裡以一句侯捷的話作為本文的結束語:“勿在浮沙築高台”。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.