c++是學習任何一門IT技術都必須要學的,在c++的學習重點和難點也就是類與封裝了,在這里我這只老鳥總結出了一些類與封裝基礎,比較全面,對c++類與封裝的入門學習必備。
一、如何定義類
定義一個類,本質上是定義一個數據類型的藍圖。這實際上并沒有定義任何數據,但它定義了類的名稱意味著什么,也就是說,它定義了類的對象包括了什么,以及可以在這個對象上執行哪些操作。
類定義是以關鍵字 class 開頭,后跟類的名稱。類的主體是包含在一對花括號中。類定義后必須跟著一個分號或一個聲明列表。
class 類名
{
成員。。。。
};
訪問限定符:
private: 私有成員變量或函數在類的外部是不可訪問的,甚至是不可查看的。只有類和友元函數可以訪問私有成員。
public: 公有成員在程序中類的外部是可訪問的?梢圆皇褂萌魏纬蓡T
函數來設置和獲取公有變量的值
protected:保護成員變量或函數與私有成員十分相似,但有一點不
同,保護成員在派生類(即子類)中是可訪問的。
什么是類的內部和類的外部?
在類的作用域范圍內叫類的內部,在類的作用域訪問外叫類的外部
注意:定義類的時候,類的成員函數可以在類的內部聲明,在類的外部定義,在外部定義的時候需要加作用域。
在表示數據類型的時候,class可以省略,直接用類名表示數據類型。
class 和struct 有什么區別?
在不加訪問限定符的情況下,class的成員默認是私有屬性,struct 的成員默認是公有屬性。
對象和類的關系:
類是某一事物的抽象,類是數據類型,對象是類的實例化,對象是變量名。
二、this指針
this指針默認在非靜態的成員函數中存在。
指向當前對象的首地址,誰調用該成員函數,誰就是當前對象。this指針在表示成員變量的時候可以省略
三、構造函數
作用:初始化成員變量,初始化只會進行一次,所以任何一個對象只會
調用一次構造函數
特點:
1.函數名和類名一樣
2.沒有返回值
3.可以重載
4.如果沒有自定義構造函數,編譯器會提供默認的構造函數進行初始化工作
5.如果自定義構造函數,對象初始化不會調用默認的構造函數,而是調用自定義的構造函數
6.構造函數不需要主動調用,創建對象的時候會自動調用構造函數進行初始化
7.構造函數可以用初始化列表進行初始化
8.構造函數通常是公有的,如果是非公有將無法創建對象
默認構造函數無入參,無打印。
拷貝(復制)構造函數 copy construct function
作用:用一個已經存在的對象給新創建的對象初始化。有默認的拷貝構造函數,如果沒有自定義,就用默認的。如果自定義拷貝構造函數,只會調用自定義的拷貝構造函數默認構造函數屬于淺拷貝
深拷貝和淺拷貝
淺拷貝: 棧內存之間數據的拷貝
深拷貝: 堆內存之間數據的拷貝四、析構函數
作用:在對象生命周期結束的時候,回收對象的資源(內存)
特點:
1.函數名是類名前加~
2.沒有返回值
3.沒有入參,不能進行函數重載
4.如果沒有自定義析構函數,編譯器會提供默認的析構函數(默認析構函數無打印,且只會釋放棧內存空間)
5.如果自定義析構函數,不會用默認的析構函數,只會用自定義的析構函數
6.析構函數不需要主動調用,在對象生命周期結束的時候自動調用
7.如果主動調用析構函數,只是執行析構函數體中的內容,并不會改變對象的生命周期。
構造函數和析構函數的順序?
構造函數按照程序執行的順序進行構造。
析構函數的執行順序由對象的生命周期來決定:
堆內存的數據是人為釋放,當你忘了人為釋放時在程序結束后會自動釋放;
棧的內存在函數結束以后就釋放,析構函數的順序和構造函數相反。
靜態數據區的內存在程序結束以后才釋放,同樣和構造的順序相反。
對象的內存空間有多大?
等于對象的成員變量的內存大小之和(滿足字節對齊)當對象沒有成員變量,對象的內存大小為1個字節
總結:
定義一個類,默認有哪些成員函數和運算符可以直接使用?1.構造函數
2.析構函數
3.拷貝構造函數
4.賦值運算符
5.&取地址運算符
四、靜態成員
加上static修飾的成員叫靜態成員,特點:屬于該類的所有對象共享的
1.靜態成員變量 本質上是全局變量,所以需要在全局范圍聲明,靜態成員變量的內存在靜態數據區,只有一份,不在對象的內存空間內。
2.靜態成員函數 可以通過類名::函數名,直接調用靜態成員函數,靜態成員函數沒有this指針。靜態成員函數訪問不了非靜態的成員變量非靜態成員函數可以訪問靜態成員變量
五、只讀成員
被const修飾的成員叫只讀成員,只讀成員只能讀不能寫,不能做左值。
1.只讀成員變量 在初始化的時候只能用初始化列表
2.只讀成員函數 不能修改成員變量的值。只讀成員函數不能調用非只讀的成員函數,非只讀的成員函數可以調用只讀的成員函數
3.只讀對象 該對象只能讀不能寫 mutable 關鍵字 (可變的)
被mutable修飾的變量不受const的約束三、友元
類的好友叫友元。友元可以訪問類的私有成員。
1.外部函數是友元 ***** 該外部函數可以訪問本類的私有成員
2.外部類是友元 *** 外部友元類的所有成員函數都可以訪問本類的私有成員
3.外部類的成員函數是友元 *** 只有聲明為友元的成員函數可以訪問本類的私有成員,其他的成員函數不行
友元具不具有傳遞性?
友元不具有傳遞性
友元的聲明不受訪問限定符的影響?偨Y什么是封裝,封裝有什么作用?
1.定義類,類中有數據和方法,模塊化編程,提高編程的效率。
2.通過訪問限定符,確定哪些成員是隱藏的,哪些是暴露在外的接口,為了數據安全性。
友元破壞了封裝,需要謹慎使用。
六、運算符重載
為什么要進行運算符重載?
1.運算符只對基本數據類型有效,對自定義的類類型無效。對象之間的運算必須要進行運算符重載
2.使用用運算符重載,使對象之間的運算變得簡單,方便。
大部分運算符都可以被重載,只有如下不能:
成員運算符. 三目運算符?: sizeof運算符 作用域運算符::
運算符重載的本質是特殊的函數:(函數名特殊)
返回值類型 operator 運算符(入參列表。。。)
{
函數體。。。。
}
類有哪些函數:
1.成員函數 類的組成部分,可以訪問類的私有成員,有this指針指代當前對象
2.友元函數 不是類的組成部分,可以類訪問私有成員,沒有this指針
3.非友元的外部函數 不能訪問類的私有成員成員函數和友元函數做運算符重載有什么區別?
友元函數比成員函數做相同的運算符重載多一個入參。原因:成員函數有this指針可以指代一個對象。
注意:運算符重載不能改變運算符的優先級和含義。
七、數據封裝
所有的 C++ 程序都有以下兩個基本要素:
程序語句(代碼):這是程序中執行動作的部分,它們被稱為函數。
程序數據:數據是程序的信息,會受到程序函數的影響。
封裝是面向對象編程中的把數據和操作數據的函數綁定在一起的一個概念,這樣能避免受到外界的干擾和誤用,從而確保了安全。數據封裝引申出了另一個重要的 OOP 概念,即數據隱藏。
數據封裝是一種把數據和操作數據的函數捆綁在一起的機制,數據抽象是一種僅向用戶暴露接口而把具體的實現細節隱藏起來的機制。數據抽象
數據抽象是指,只向外界提供關鍵信息,并隱藏其后臺的實現細節,即只表現必要的信息而不呈現細節。
數據抽象是一種依賴于接口和實現分離的編程(設計)技術。
舉一個現實生活中的真實例子,比如一臺電視機,您可以打開和關閉、切換頻道、調整音量、添加外部組件(如喇叭、錄像機、DVD 播放器),但是您不知道它的內部實現細節,也就是說,您并不知道它是如何通過纜線接收信號,如何轉換信號,并最終顯示在屏幕上。
因此,我們可以說電視把它的內部實現和外部接口分離開了,您無需知道它的內部實現原理,直接通過它的外部接口(比如電源按鈕、遙控器、聲量控制器)就可以操控電視。
數據抽象的好處
數據抽象有兩個重要的優勢:
類的內部受到保護,不會因無意的用戶級錯誤導致對象狀態受損。類實現可能隨著時間的推移而發生變化,以便應對不斷變化的需求,或者應對那些要求不改變用戶級代碼的錯誤報告。
如果只在類的私有部分定義數據成員,編寫該類的作者就可以隨意更改數據。如果實現發生改變,則只需要檢查類的代碼,看看這個改變會導致哪些影響。如果數據是公有的,則任何直接訪問舊表示形式的數據成員的函數都可能受到影響。