注意事項
對于不帶.h的頭文件,所有的符號都位于命名空間 std 中,使用時需要聲明命名空間 std;對于帶.h的頭文件,沒有使用任何命名空間,所有符號都位于全局作用域。這也是 C++ 標(biāo)準(zhǔn)所規(guī)定的。
在 main() 函數(shù)中聲明命名空間 std,它的作用范圍就位于 main() 函數(shù)內(nèi)部,如果在其他函數(shù)中又用到了 std,就需要重新聲明。如果希望在所有函數(shù)中都使用命名空間 std,可以將它聲明在全局范圍中。將 std 直接聲明在所有函數(shù)外部,這樣雖然使用方便,但在中大型項目開發(fā)中是不被推薦的,這樣做增加了命名沖突的風(fēng)險
.c是C語言代碼,.cpp是C++代碼,它們的編譯方式不同
要在函數(shù)定義處添加 inline 關(guān)鍵字,在函數(shù)聲明處添加 inline 關(guān)鍵字雖然沒有錯,但這種做法是無效的,編譯器會忽略函數(shù)聲明處的 inline 關(guān)鍵字。
C++規(guī)定,默認(rèn)參數(shù)只能放在形參列表的最后,而且一旦為某個形參指定了默認(rèn)值,那么它后面的所有形參都必須有默認(rèn)值。實參和形參的傳值是從左到右依次匹配的,默認(rèn)參數(shù)的連續(xù)性是保證正確傳參的前提
函數(shù)的重載實現(xiàn)中參數(shù)列表不同包括參數(shù)的個數(shù)不同、類型不同或順序不同,僅僅參數(shù)名稱不同是不可以的。函數(shù)返回值也不能作為重載的依據(jù)。C++代碼在編譯時會根據(jù)參數(shù)列表對函數(shù)進(jìn)行重命名,例如void Swap(int a, int b)會被重命名為_Swap_int_int,void Swap(float x, float y)會被重命名為_Swap_float_float,從這個角度講,函數(shù)重載僅僅是語法層面的,本質(zhì)上它們還是不同的函數(shù),占用不同的內(nèi)存,入口地址也不一樣。
Student stu創(chuàng)建的對象 stu 在棧上分配內(nèi)存,Student *pStu = new Student在堆上創(chuàng)建對象,使用 new 在堆上創(chuàng)建出來的對象是匿名的,沒法直接使用,必須要用一個指針指向它,再借助指針來訪問它的成員變量或成員函數(shù)。棧內(nèi)存是程序自動管理的,不能使用 delete 刪除在棧上創(chuàng)建的對象;堆內(nèi)存由程序員管理,對象使用完畢后可以通過 delete 刪除
類的成員變量和普通變量一樣,也有數(shù)據(jù)類型和名稱,占用固定長度的內(nèi)存。但是,在定義類的時候不能對成員變量賦值,因為類只是一種數(shù)據(jù)類型或者說是一種模板,本身不占用內(nèi)存空間,而變量的值則需要內(nèi)存來存儲。
類的成員函數(shù)也和普通函數(shù)一樣,都有返回值和參數(shù)列表,它與一般函數(shù)的區(qū)別是:成員函數(shù)是一個類的成員,出現(xiàn)在類體中,它的作用范圍由類來決定;而普通函數(shù)是獨立的,作用范圍是全局的,或位于某個命名空間內(nèi)。
在類體中和類體外定義成員函數(shù)是有區(qū)別的:在類體中定義的成員函數(shù)會自動成為內(nèi)聯(lián)函數(shù),在類體外定義的不會。
在類的內(nèi)部(定義類的代碼內(nèi)部),無論成員被聲明為 public、protected 還是 private,都是可以互相訪問的,沒有訪問權(quán)限的限制。
在類的外部(定義類的代碼之外),只能通過對象訪問成員,并且通過對象只能訪問 public 屬性的成員,不能訪問 private、protected 屬性的成員。
給成員變量賦值的函數(shù)通常稱為 set 函數(shù),它們的名字通常以set開頭,后跟成員變量的名字;讀取成員變量的值的函數(shù)通常稱為 get 函數(shù),它們的名字通常以get開頭,后跟成員變量的名字。
在棧上創(chuàng)建對象時,實參位于對象名后面,例如Student stu("小明", 15, 92.5f);在堆上創(chuàng)建對象時,實參位于類名后面,例如new Student("李華", 16, 96)。調(diào)用沒有參數(shù)的構(gòu)造函數(shù)也可以省略括號 例如Student stu
構(gòu)造函數(shù)必須是 public 屬性的,否則創(chuàng)建對象時無法調(diào)用。當(dāng)然,設(shè)置為 private、protected 屬性也不會報錯,但是沒有意義。構(gòu)造函數(shù)沒有返回值,因為沒有變量來接收返回值,函數(shù)體中不能有 return 語句
構(gòu)造函數(shù)是允許重載的。一個類可以有多個重載的構(gòu)造函數(shù),構(gòu)造函數(shù)的調(diào)用是強制性的,一旦在類中定義了構(gòu)造函數(shù),那么創(chuàng)建對象時就一定要調(diào)用,不調(diào)用是錯誤的一個類必須有構(gòu)造函數(shù),要么用戶自己定義,要么編譯器自動生成。一旦用戶自己定義了構(gòu)造函數(shù),不管有幾個,也不管形參如何,編譯器都不再自動生成。
成員變量的初始化順序與初始化列表中列出的變量的順序無關(guān),它只與成員變量在類中聲明的順序有關(guān)。
構(gòu)造函數(shù)初始化列表有一個很重要的作用,那就是初始化 const 成員變量。初始化 const 成員變量的唯一方法就是使用初始化列表
this 是 const 指針,它的值是不能被修改的,一切企圖修改該指針的操作,如賦值、遞增、遞減等都是不允許的。this 只能在成員函數(shù)內(nèi)部使用,用在其他地方?jīng)]有意義,也是非法的。只有當(dāng)對象被創(chuàng)建后 this 才有意義,因此不能在 static 成員函數(shù)中使用。
this 實際上是成員函數(shù)的一個形參,在調(diào)用成員函數(shù)時將對象的地址作為實參傳遞給 this。不過 this 這個形參是隱式的,它并不出現(xiàn)在代碼中,而是在編譯階段由編譯器默默地將它添加到參數(shù)列表中。this 作為隱式形參,本質(zhì)上是成員函數(shù)的局部變量,所以只能用在成員函數(shù)的內(nèi)部,并且只有在通過對象調(diào)用成員函數(shù)時才給 this 賦值。
成員函數(shù)最終被編譯成與對象無關(guān)的普通函數(shù),除了成員變量,會丟失所有信息,所以編譯時要在成員函數(shù)中添加一個額外的參數(shù),把當(dāng)前對象的首地址傳入,以此來關(guān)聯(lián)成員函數(shù)和成員變量。這個額外的參數(shù),實際上就是 this,它是成員函數(shù)和成員變量關(guān)聯(lián)的橋梁。
static
- static 成員變量屬于類,不屬于某個具體的對象,即使創(chuàng)建多個對象,也只為 m_total 分配一份內(nèi)存,所有對象使用的都是這份內(nèi)存中的數(shù)據(jù)。當(dāng)某個對象修改了 m_total,也會影響到其他對象
24 static 成員變量的內(nèi)存既不是在聲明類時分配,也不是在創(chuàng)建對象時分配,而是在(類外)初始化時分配。反過來說,沒有在類外初始化的 static 成員變量不能使用。靜態(tài)成員變量在初始化時不能再加 static,但必須要有數(shù)據(jù)類型。被 private、protected、public 修飾的靜態(tài)成員變量都可以用這種方式初始化。
- static 成員變量既可以通過對象來訪問,也可以通過類來訪問, static 成員變量不占用對象的內(nèi)存,而是在所有對象之外開辟內(nèi)存,即使不創(chuàng)建對象也可以訪問
26。 static 成員變量和普通 static 變量一樣,都在內(nèi)存分區(qū)中的全局?jǐn)?shù)據(jù)區(qū)分配內(nèi)存,到程序結(jié)束時才釋放。這就意味著,static 成員變量不隨對象的創(chuàng)建而分配內(nèi)存,也不隨對象的銷毀而釋放內(nèi)存。而普通成員變量在對象創(chuàng)建時分配內(nèi)存,在對象銷毀時釋放內(nèi)存。靜態(tài)成員變量必須初始化,而且只能在類體外進(jìn)行,初始化時可以賦初值,也可以不賦值。如果不賦值,那么會被默認(rèn)初始化為 0
編譯器在編譯一個普通成員函數(shù)時,會隱式地增加一個形參 this,并把當(dāng)前對象的地址賦值給 this,所以普通成員函數(shù)只能在創(chuàng)建對象后通過對象來調(diào)用,因為它需要當(dāng)前對象的地址。而靜態(tài)成員函數(shù)可以通過類來直接調(diào)用,編譯器不會為它增加形參 this,它不需要當(dāng)前對象的地址,所以不管有沒有創(chuàng)建對象,都可以調(diào)用靜態(tài)成員函數(shù)
普通成員變量占用對象的內(nèi)存,靜態(tài)成員函數(shù)沒有 this 指針,不知道指向哪個對象,無法訪問對象的成員變量,也就是說靜態(tài)成員函數(shù)不能訪問普通成員變量,只能訪問靜態(tài)成員(包括靜態(tài)成員變量和靜態(tài)成員函數(shù))。
const
常成員函數(shù)需要在聲明和定義的時候在函數(shù)頭部的結(jié)尾加上 const 關(guān)鍵字,必須在成員函數(shù)的聲明和定義處同時加上 const 關(guān)鍵字,如果只在一個地方加 const 會導(dǎo)致聲明和定義處的函數(shù)原型沖突
const 也可以用來修飾對象,稱為常對象。一旦將對象定義為常對象之后,就只能調(diào)用類的 const 成員(包括 const 成員變量和 const 成員函數(shù))了,因為非 const 成員可能會修改對象的數(shù)據(jù)(編譯器也會這樣假設(shè)),C++禁止這樣做。
友元函數(shù)不同于類的成員函數(shù),在友元函數(shù)中不能直接訪問類的成員,必須要借助對象
類的提前聲明的使用范圍是有限的,只有在正式聲明一個類以后才能用它去創(chuàng)建對象。。因為創(chuàng)建對象時要為對象分配內(nèi)存,在正式聲明類之前,編譯器無法確定應(yīng)該為對象分配多大的內(nèi)存。編譯器只有在“見到”類的正式聲明后(其實是見到成員變量),才能確定應(yīng)該為對象預(yù)留多大的內(nèi)存。在對一個類作了提前聲明后,可以用該類的名字去定義指向該類型對象的指針變量(本例就定義了 Address 類的指針變量)或引用變量(后續(xù)會介紹引用),因為指針變量和引用變量本身的大小是固定的,與它所指向的數(shù)據(jù)的大小無關(guān)。
總結(jié)
成員函數(shù)之間可以互相調(diào)用,成員函數(shù)內(nèi)部可以訪問成員變量。
私有成員只能在類的成員函數(shù)內(nèi)部訪問。默認(rèn)情況下,class 類的成員是私有的,struct 類的成員是公有的。
可以用“對象名.成員名”、“引用名.成員名”、“對象指針->成員名”的方法訪問對象的成員變量或調(diào)用成員函數(shù)。成員函數(shù)被調(diào)用時,可以用上述三種方法指定函數(shù)是作用在哪個對象上的。
對象所占用的存儲空間的大小等于各成員變量所占用的存儲空間的大小之和(如果不考慮成員變量對齊問題的話)。
定義類時,如果一個構(gòu)造函數(shù)都不寫,則編譯器自動生成默認(rèn)(無參)構(gòu)造函數(shù)和復(fù)制構(gòu)造函數(shù)。如果編寫了構(gòu)造函數(shù),則編譯器不自動生成默認(rèn)構(gòu)造函數(shù)。一個類不一定會有默認(rèn)構(gòu)造函數(shù),但一定會有復(fù)制構(gòu)造函數(shù)。
任何生成對象的語句都要說明對象是用哪個構(gòu)造函數(shù)初始化的。即便定義對象數(shù)組,也要對數(shù)組中的每個元素如何初始化進(jìn)行說明。如果不說明,則編譯器認(rèn)為對象是用默認(rèn)構(gòu)造函數(shù)或參數(shù)全部可以省略的構(gòu)造函數(shù)初始化。在這種情況下,如果類沒有默認(rèn)構(gòu)造函數(shù)或參數(shù)全部可以省略的構(gòu)造函數(shù),則編譯出錯。
每個對象有各自的一份普通成員變量,但是靜態(tài)成員變量只有一份,被所有對象所共享。靜態(tài)成員函數(shù)不具體作用于某個對象。即便對象不存在,也可以訪問類的靜態(tài)成員。靜態(tài)成員函數(shù)內(nèi)部不能訪問非靜態(tài)成員變量,也不能調(diào)用非靜態(tài)成員函數(shù)。
常量對象上面不能執(zhí)行非常量成員函數(shù),只能執(zhí)行常量成員函數(shù)。
包含成員對象的類叫封閉類。任何能夠生成封閉類對象的語句,都要說明對象中包含的成員對象是如何初始化的。如果不說明,則編譯器認(rèn)為成員對象是用默認(rèn)構(gòu)造函數(shù)或參數(shù)全部可以省略的構(gòu)造函數(shù)初始化。
在封閉類的構(gòu)造函數(shù)的初始化列表中可以說明成員對象如何初始化。封閉類對象生成時,先執(zhí)行成員對象的構(gòu)造函數(shù),再執(zhí)行自身的構(gòu)造函數(shù);封閉類對象消亡時,先執(zhí)行自身的析構(gòu)函數(shù),再執(zhí)行成員對象的析構(gòu)函數(shù)。
const 成員和引用成員必須在構(gòu)造函數(shù)的初始化列表中初始化,此后值不可修改。
友元分為友元函數(shù)和友元類。友元關(guān)系不能傳遞。
成員函數(shù)中出現(xiàn)的 this 指針,就是指向成員函數(shù)所作用的對象的指針。因此,靜態(tài)成員函數(shù)內(nèi)部不能出現(xiàn) this 指針。成員函數(shù)實際上的參數(shù)個數(shù)比表面上看到的多一個,多出來的參數(shù)就是 this 指針