日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

.net知識(shí)和學(xué)習(xí)方法系列(十五)類型,對(duì)象,堆棧和托管堆 - 片言程序 - 博客園

 nbxming 2010-11-14

 

1、          類型,對(duì)象,堆棧和托管堆

C#的類型和對(duì)象在應(yīng)用計(jì)算機(jī)內(nèi)存時(shí),大體用到兩種內(nèi)存,一個(gè)叫堆棧,另一個(gè)叫托管堆,下面我們用直角長方形來代表堆棧,用圓角長方形來代表托管堆。

 

 

首先討論一下方法內(nèi)部變量的存放。

先舉個(gè)例子,有如下兩個(gè)方法,Method_1Add,分別如下:

public void Method_1()

{

 int value1=10;  //1

 int value2=20;    //2

 int value3=Add(value,value); //3

}

public int Add(int n1,int n2)//4

{

   rnt sum=n1+n2;//5

   return sum;//6

}

這段代碼的執(zhí)行,用圖表示為:

 

上述的每個(gè)圖片,基本對(duì)應(yīng)程序中的每個(gè)步驟。在開始執(zhí)行Method_1的時(shí)候,先把value1壓入堆棧頂,然后是value2,接下來的是調(diào)用方法Add,因?yàn)榉椒ㄓ袃蓚€(gè)參數(shù)是n1n2,所以把n1n2分別壓入堆棧,因?yàn)榇颂幨钦{(diào)用了一個(gè)方法,并且方法有返回值,所以這里需要保存Add的返回地址,然后進(jìn)入Add方法內(nèi)部,在Add內(nèi)部,首先是給sum賦值,所以把sum壓入棧項(xiàng),然后用return返回,此時(shí),先前的返回地址就起到了作用,return會(huì)根據(jù)地址返回去的,在返回的過程中,把sum推出棧頂,找到了返回地址,但在Method_1方法中,我們希望把Add的返回值賦給value3,此時(shí)的返回地址也被推出堆棧,把value3壓入堆棧。雖這個(gè)例子的結(jié)果在這里沒有多大用途,但這個(gè)例子很好的說明了在方法被執(zhí)行時(shí),變量與進(jìn)出堆棧的情況。這里也能看出為什么方法內(nèi)部的局變量用過后,不能在其他方法中訪問的原因。

 

其次來討論一下類和對(duì)象在托管堆和堆棧中的情況。

先看一下代碼:

    class Car

    {

        public void Run()

        {

            Console.WriteLine("一切正常");

        }

        public virtual double GetPrice()

        {

            return 0;

        }

        public static void Purpose()

        {

            Console.WriteLine("載人");

        }

    }

    class BMW : Car

    {

        public override double GetPrice()

        {

            return 800000;

        }

}

上面是兩個(gè)類,一個(gè)Father一個(gè)Son,Son繼承了Father,因?yàn)槟泐愔杏幸粋€(gè)virtual的BuyHouse方法,所以Son類可以重寫這個(gè)方法。

下面接著看調(diào)用代碼。

        public void Method_A()

        {

            double CarPrice;//1

            Car car = new BMW();//2

            CarPrice = car.GetPrice();//調(diào)用虛方法(其實(shí)調(diào)用的是重寫后的方法)

            car.Run();//調(diào)用實(shí)例化方法

            Car.Purpose();//調(diào)用靜態(tài)方法

 }

這個(gè)方法也比較簡單,就是定義一個(gè)變量用來獲得價(jià)格,同時(shí)定義了一個(gè)父類的變量,用子類來實(shí)例化它。

接下來,我們分步來說明。

看一下運(yùn)行時(shí)堆棧和托管堆的情部我:

 

這里需要說明的是,類是位于托管堆中的,每個(gè)類又分為四個(gè)類部,類指針,用來關(guān)聯(lián)對(duì)象;同步索引,用來完成同步(比如線程的同步)需建立的;靜態(tài)成員是屬于類的,所以在類中出現(xiàn),還有一個(gè)方法列表(這里的方法列表項(xiàng)與具體的方法對(duì)應(yīng))。

當(dāng)Method_A方法的第一步執(zhí)行時(shí): 

 這時(shí)的CarPrice是沒有值的

當(dāng)Method_A方法執(zhí)行到第二步,其實(shí)第二步又可以分成

Car car;

 car = new BMW();

先看Car car;

 


car在這里是一個(gè)方法內(nèi)部的變量,所以被壓到堆棧中。

 再看 car = new BMW();

這是一個(gè)實(shí)例化過程,car變成了一個(gè)對(duì)象

 

 


這里是用子類來實(shí)例化父類型。對(duì)象其實(shí)是子類的類型的,但變量的類型是父類的。

接下來,在Method_A中的調(diào)用的中調(diào)用car.GetPrice(),對(duì)于Car來說,這個(gè)方法是虛方法(并且子類重寫了它),虛方法在調(diào)用是不會(huì)執(zhí)行類型上的方法,即不會(huì)執(zhí)行Car類中的虛方法,而是執(zhí)行對(duì)象對(duì)應(yīng)類上的方法,即 BMW中的GtPrice。

如果Method_A中執(zhí)行方法Run(),因?yàn)?/span>Run是普通實(shí)例方法,所以會(huì)執(zhí)行Car類中的Run方法。

如果調(diào)用了Method_APurpose方法,即不用變量car調(diào)用,也不用對(duì)象調(diào)用,而是用類名Car調(diào)用,因?yàn)殪o態(tài)方法會(huì)在類中分配內(nèi)存的。如果用Car生成多個(gè)實(shí)例,靜態(tài)成員只有一份,就是在類中,而不是在對(duì)象中

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多