c++學習雜記(2)

類和結構:

  class和struct的比較:struct是簡化數據邏輯結構的設計,本質上屬於自定義的數據結構;class是將數據與方法封裝,讓行爲和數據一致,本質上是一種程序設計方法,折射了一種編程思想。struct不能包括函數,而class可以,在struct裏成員默認屬性(存儲控制)是private而struct默認屬性是public。

c的struct和c++的struct的區別:在c中說明結構對象的方法是:struct xxxx a;c++爲:xxxx a,struct可以不用。

                                                         c中結構不能有成員函數,c++的struct可以有。

                                                          c++種class和struct的區別:存儲控制不同。

個人認爲c++種的結構應該屬於class的範疇。

class:

在類裏定義的成員函數規模小,而且奴允許用switch語句,默認爲inline函數,其調用在源程序中原地擴展,不調用堆棧,故可以放在頭文件裏,而一般函數的定義不能放在頭文件裏,因爲這意味着它將被編譯多次。

最好將類定義和成員函數定義分開,將類定義視爲類的外部接口,而成員函數視爲其內部實現。將類成員定義爲私有成員函數定義爲公有是很好的風格。

類名是類成員函數的一部分,故不同類的內部同名的成員函數,不能視爲重載。

當一個類有多個實例時,每個成員函數都調用同一段代碼,那該成員函數這麼識別數據是屬於不同的實例呢?其實當成員函數接受實參時,還接受了具體實例的地址,而且這個地址被隱藏的形參this獲得即this=&xx,故訪問的數據成員前都隱含加了this->,這就是類成員函數操作本類數據成員不需要像其他函數加類前綴的原因。

一個類實例所佔內存大小由數據成員所佔空間的總和決定,當然與成員函數無關。

類的作用域:

類的作用域是指類定義和成員函數對應的範圍,類成員函數對類數據成員有無限制的訪問權限。

在成員函數定義與類成員同名的局部作用域變量後就把類成員隱蔽了。類型名可以與變量名或函數名相同,如果非類型名隱藏了類型名,則類型名加前綴即可:

void func(int Sample)

{

class Sample a;

Sample++;

.......

}

如果類型名隱藏了非類型名,用作用域規則即可:

int S;

void func()

{

class S {....};

S s;

::S=3;

}

注:在函數中定義的類叫局部類,局部類的作用域在定義該類的函數塊中,局部類的成員函數必須在局部類的內部定義,若在類外函數內定義造成函數嵌套定義,若在在包括類的函數外定義則成員函數無法與類取得聯繫。

一個名字不能同時指兩種類型非類型名(變量,常量,函數,對象,枚舉成員)不能重名。在同一個作用域中,一個名字可以同時聲明爲類型和非類型,同時登場時加各自的前綴即可區別。

構造函數:

構造函數無返回類型,自動調用,無返回值,但可以有無值return語句,不能爲virtual(可以爲(包括拷貝構造函數)virtual,只是不經常用,現在糾正),可以重載。當類中含有其他類時,各自的構造函數工作如下(最簡單的情況):如A中有B,C

當需要創建A的對象時,調用A的構造函數,該構造函數啓動,首先分配對象空間,然後按類成員聲明順序依次調用其構造函數,最後才執行A的構造函數的函數體,最後控制返回主函數。

無參數的構造函數叫默認構造函數,顯式調用構造函數會創建一個無名對象。

注:c++語法規定,無構造函數的類無法創建對象。若未提供構造函數,那麼編譯器會自動提供一個默認構造數,無參。只要爲一個類定義了一個構造函數以上,編譯器不再提供默認構造函數,若還想要無參構造函數,必須自己定義。當創建無參對象時不能有括號:

                                                                 class A

                                                                   {

                                                                     public:A(){}

                                                                    };

                                                                     A a();//錯誤...............1

                                                                     A b;//正確...................2

其原因是:c++語法規定,1聲明瞭一個函數A只是它的返回類型;

                    Class a(10);................創建對象

                    Class b(int);................創建函數

如下程序:

                   class A

                     {

                      pubilc:

                      A(int id=0)

                      {

                                 value = id;

                       }

                       protected:

                       int value;

                      };

                       class B

                       {

                        public:

                        B(....,int id = 0)

                        {

                         A a(id);

                        .........

                         }

                         protected:

                          A a;

                        };

                        main ()

                       {

                        B b(......,32);

                         }

無法將32傳給value;因爲在構造函數中的A a只是個局部變量,當構造函數結束後就被析構了,value爲0,正確的方法是去掉前面的“A”

如果在上面B中加入類似於A a(12);等東西,在B定義時不會調用A的構造函數。

局部和static對象以聲明的順序構造,而且這些對象在函數開始執行時同一定義,其順序與出現順序相同,而不是按運行順序來決定變量定義順序。

文件作用域的static在main()之前全部構造完畢,塊作用域中的static對象在首次進入定義該對象的函數時被構造。全局對象在main()函數之前全部被構造,其順序隨機,故禁止一個全局對象訪問另一個全局對象。類成員在類中以聲明的順序被構造。

析構函數:

析構函數無返回類型,無參,不能隨意調用無重載,最好爲virtual,當多類包含時,析構函數調用與構造函數相反。

 

類和結構:

  class和struct的比較:struct是簡化數據邏輯結構的設計,本質上屬於自定義的數據結構;class是將數據與方法封裝,讓行爲和數據一致,本質上是一種程序設計方法,折射了一種編程思想。struct不能包括函數,而class可以,在struct裏成員默認屬性(存儲控制)是private而struct默認屬性是public。

c的struct和c++的struct的區別:在c中說明結構對象的方法是:struct xxxx a;c++爲:xxxx a,struct可以不用。

                                                         c中結構不能有成員函數,c++的struct可以有。

                                                          c++種class和struct的區別:存儲控制不同。

個人認爲c++種的結構應該屬於class的範疇。

class:

在類裏定義的成員函數規模小,而且奴允許用switch語句,默認爲inline函數,其調用在源程序中原地擴展,不調用堆棧,故可以放在頭文件裏,而一般函數的定義不能放在頭文件裏,因爲這意味着它將被編譯多次。

最好將類定義和成員函數定義分開,將類定義視爲類的外部接口,而成員函數視爲其內部實現。將類成員定義爲私有成員函數定義爲公有是很好的風格。

類名是類成員函數的一部分,故不同類的內部同名的成員函數,不能視爲重載。

當一個類有多個實例時,每個成員函數都調用同一段代碼,那該成員函數這麼識別數據是屬於不同的實例呢?其實當成員函數接受實參時,還接受了具體實例的地址,而且這個地址被隱藏的形參this獲得即this=&xx,故訪問的數據成員前都隱含加了this->,這就是類成員函數操作本類數據成員不需要像其他函數加類前綴的原因。

一個類實例所佔內存大小由數據成員所佔空間的總和決定,當然與成員函數無關。

類的作用域:

類的作用域是指類定義和成員函數對應的範圍,類成員函數對類數據成員有無限制的訪問權限。

在成員函數定義與類成員同名的局部作用域變量後就把類成員隱蔽了。類型名可以與變量名或函數名相同,如果非類型名隱藏了類型名,則類型名加前綴即可:

void func(int Sample)

{

class Sample a;

Sample++;

.......

}

如果類型名隱藏了非類型名,用作用域規則即可:

int S;

void func()

{

class S {....};

S s;

::S=3;

}

注:在函數中定義的類叫局部類,局部類的作用域在定義該類的函數塊中,局部類的成員函數必須在局部類的內部定義,若在類外函數內定義造成函數嵌套定義,若在在包括類的函數外定義則成員函數無法與類取得聯繫。

一個名字不能同時指兩種類型非類型名(變量,常量,函數,對象,枚舉成員)不能重名。在同一個作用域中,一個名字可以同時聲明爲類型和非類型,同時登場時加各自的前綴即可區別。

構造函數:

構造函數無返回類型,自動調用,無返回值,但可以有無值return語句,不能爲virtual,可以重載。當類中含有其他類時,各自的構造函數工作如下(最簡單的情況):如A中有B,C

當需要創建A的對象時,調用A的構造函數,該構造函數啓動,首先分配對象空間,然後按類成員聲明順序依次調用其構造函數,最後才執行A的構造函數的函數體,最後控制返回主函數。

無參數的構造函數叫默認構造函數,顯式調用構造函數會創建一個無名對象。

注:c++語法規定,無構造函數的類無法創建對象。若未提供構造函數,那麼編譯器會自動提供一個默認構造數,無參。只要爲一個類定義了一個構造函數以上,編譯器不再提供默認構造函數,若還想要無參構造函數,必須自己定義。當創建無參對象時不能有括號:

                                                                 class A

                                                                   {

                                                                     public:A(){}

                                                                    };

                                                                     A a();//錯誤...............1

                                                                     A b;//正確...................2

其原因是:c++語法規定,1聲明瞭一個函數A只是它的返回類型;

                    Class a(10);................創建對象

                    Class b(int);................創建函數

但是 Class * ptr=new Class();//如果Class類有默認構造函數的話可以。注意這和上面有本質區別。

如下程序:

                   class A

                     {

                      pubilc:

                      A(int id=0)

                      {

                                 value = id;

                       }

                       protected:

                       int value;

                      };

                       class B

                       {

                        public:

                        B(....,int id = 0)

                        {

                         A a(id);

                        .........

                         }

                         protected:

                          A a;

                        };

                        main ()

                       {

                        B b(......,32);

                         }

無法將32傳給value;因爲在構造函數中的A a只是個局部變量,當構造函數結束後就被析構了,value爲0,正確的方法是去掉前面的“A”

如果在上面B中加入類似於A a(12);等東西,在B定義時不會調用A的構造函數。

局部和static對象以聲明的順序構造,而且這些對象在函數開始執行時同一定義,其順序與出現順序相同,而不是按運行順序來決定變量定義順序。

文件作用域的static在main()之前全部構造完畢,塊作用域中的static對象在首次進入定義該對象的函數時被構造。全局對象在main()函數之前全部被構造,其順序隨機,故禁止一個全局對象訪問另一個全局對象。類成員在類中以聲明的順序被構造。

析構函數:

析構函數無返回類型,無參,不能隨意調用無重載,最好爲virtual,當多類包含時,析構函數調用與構造函數相反。

堆與拷貝構造函數:

堆:

1.一個進程在創建時都分配一個靜態存儲區域、一個堆、一個棧,代碼區

2.靜態存儲區域用於存儲進程的全局變量和靜態變量;全局變量和靜態變量從靜態存儲區域分配。程序在編譯的時候就已經分配好內存的分佈,這塊內存在程序的整個運行期間都存在。

3.堆
1)程序在運行的時候用malloc或new從堆上動態申請任意多少的內存,程序員自己負責在何時用free或delete釋放內存。
2)堆應該是保留的一段內存空間,在進程初始化的時候,系統會提交一部分物理存儲。進程的堆的初始大小默認是1MB。物理存貯的提交和回收應該是由堆管理器來管理的。堆應該是自動增長的。我們說的“自動生長”指的是在預先保留的全部堆空間都不夠用的時候,重新來從自由區域留。                                                                                  

3)堆對象的作用域是整個程序生命期。在對上分配數組,只能調用默認構造函數。若沒有,出錯!

4.每一個函數都可以對棧操作,用於存儲參數和局部變量。
1)在執行函數時,函數的參數和函數內的局部變量及調用相關信息(局部變量,函數參數,返回數據,返回地址)的存儲單元都可以在棧上創建,函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置於處理器的指令集中,效率很高,但是分配的內存容量有限
2)(在函數內)聲明變量/數組的方式,是在棧中分配內存。當調用完此函數返回的時候,棧空間自動被收回,其中的內容也就全部無效了。

在c++中malloc()函數分配空間的時候不能調用構造函數,由於類對象的建立是分配空間,構造結構和初始化三位一體故malloc()無法達到要求,它會返回一個非法對象的數據空間,同理,free也不會調用析構函數。

拷貝構造函數:

xxx(xxx&)參數是xxx&。拷貝構造函數的必要性,對象不同於基本數據,部分對象還申請了系統資源若s對象有一個資源,用它創建t,如果只是二進制內存空間的拷貝,那麼t也擁有了這個資源,故會導致資源管理器的混亂。若未提供一個拷貝構造函數,編譯器將會提供一個默認的拷貝構造函數,它只完成一個成員到另一個成員的拷貝,如果成員是類對象,則會調用它的拷貝或默認拷貝構造函數。

淺拷貝和深拷貝:當對象與資源聯繫(如堆,打開文件,佔有硬件等),如果簡單的進行拷貝(淺拷貝),會形成多個對象擁有一個資源故我們必須定義自己的拷貝構造函數,堆資源也進行拷貝(深拷貝)。

臨時對象:

當函數返回一個對象時,要建立一個臨時對象用以存放返回對象:被調用函數棧區->臨時對象->main棧區。設a=f(n),當返回的臨時對象賦給啊a後,臨時對象就被析構了(故不要對其引用和取指針)。

構造函數用於類型轉換:

 如果目的類有以原始類爲參數(只能一個)的構造函數,那麼就可以。

靜態成員和友元:

靜態成員包括靜態成員函數和靜態數據成員

靜態成員作用:讓一個類的所有對象共享一個類成員(數據成員只初始化一次)。

在類對象的空間中並沒有static數據成員的位置,它的空間不會隨對象的產生而分配,或隨對象的析構而消失,空間的回收也不在析構函數裏完成。靜態數據成員應該在程序開始運行就存在的。由於靜態成員要實際分配地址空間,因而不能在類定義中寫成定義,它也不能在頭文件中類的聲明外定義,會造成多個適用該頭文件的源文件對其重複定義,靜態成員也不能在main()函數之前的定義全局數據處定義,那會造成每個要使用該類的應用程序每次都要重新定義。故最好放在類定義的實現部分定義再合適不過。(前面都是廢話:))

 static數據成員的訪問控制與一般成員差不多

注:靜態數據成員只有屬於哪個類的說法,沒有屬於哪個對象的說法。調用用::符號。不用.符號。

靜態成員函數:與類聯繫,不與對象聯繫,訪問用:: 符號,由於靜態成員函數不與任何對象聯繫,故不能用靜態成員函數對非靜態成員作默認訪問。

靜態成員函數和非靜態成員函數的根本區別是:靜態成員函數沒有this指針,而非靜態成員函數都有指向當前對象的this指針。

友元部分略

類中的const數據也是在類外用::初始化   或者用初始化列表

發佈了17 篇原創文章 · 獲贊 4 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章