一、this指標
1、C++程式到C程式的翻譯
class CCar { struct CCar { public: int price; int price; }; void SetPrice(int p); void SetPrice(struct CCar * this,int p){}; this->price = p;void CCar::SetPrice(int p){ } price = p; //this->price = p;} int main() {int main(){ struct CCar car; CCar car; SetPrice( & car,20000); car.SetPrice(20000); return 0; return 0; }}
2、this指標作用:非靜態成員函數中可以直接使用this來代表指向該函數作用的對象的指標
3、this指標和靜態成員函數:靜態成員函數並不具體作用與某個對象,所以靜態成員函數中不能使用 this 指標
二、靜態成員
靜態成員:在說明前面加了static關鍵字的成員。
普通成員變數每個對象有各自的一份,而靜態成員變數一共就一份,為所有對象共用,sizeof 運算子不會計算靜態成員變數。
普通成員函數必須具體作用於某個對象,而靜態成員函數並不具體作用於某個對象,不需要通過對象就能訪問。
class CRectangle{ private: int w, h; static int nTotalArea; // 靜態成員變數 public: CRectangle(int w_,int h_); ~CRectangle(); static void PrintTotal(); // 靜態成員函數};
1、訪問靜態成員的方法:
類名::成員名 CRectangle::PrintTotal();
對象名.成員名 CRectangle r; r.PrintTotal();
指標->成員名 CRectangle * p = &r; p->PrintTotal();
引用.成員名 CRectangle & ref = r; int n = ref.nTotalNumber;
2、注意事項:
靜態成員變數本質上是全域變數,哪怕一個對象都不存在,類的靜態成員變數也存在
必須在定義類的檔案中對靜態成員變數進行一次說明或初始化。否則編譯能通過,連結不能通過
在靜態成員函數中,不能訪問非靜態成員變數,也不能調用非靜態成員函數
三、成員對象和封閉類
1、定義:有成員對象的類叫 封閉(enclosing)類
class CTyre{ // 輪胎類 private: int radius; // 半徑 int width; // 寬度 public: CTyre(int r,int w):radius(r),width(w) { }};class CEngine{ // 引擎類};class CCar { // 汽車類 private: int price; // 價格 CTyre tyre; CEngine engine; public: CCar(int p,int tr,int tw );};CCar::CCar(int p,int tr,int w):price(p),tyre(tr, w){};int main(){ CCar car(20000,17,225); return 0;}
上例中,如果 CCar類不定義建構函式, 則下面的語句會編譯出錯:CCar car;因為編譯器不明白 car.tyre該如何初始化。car.engine 的初始化沒問題,用預設建構函式即可。任何產生封閉類對象的語句,都要讓編譯器明白,對象中的成員對象,是如何初始化的。具體的做法就是:通過封閉類的建構函式的初始化列表。
2、封閉類建構函式和解構函式的執行順序
封閉類對象產生時,先執行所有對象成員的建構函式,然後才執行封閉類的建構函式。
對象成員的建構函式調用次序和對象成員在類中的說明次序一致,與它們在成員初始化列表中出現的次序無關。
當封閉類的對象消亡時,先執行封閉類的解構函式,然後再執行成員對象的解構函式。次序和建構函式的調用次序相反。
class CTyre { public: CTyre() { cout << "CTyre contructor" << endl; } ~CTyre() { cout << "CTyre destructor" << endl; }};class CEngine { public: CEngine() { cout << "CEngine contructor" << endl; } ~CEngine() { cout << "CEngine destructor" << endl; }};class CCar { private: CEngine engine; CTyre tyre; public: CCar( ) { cout << “CCar contructor” << endl; } ~CCar() { cout << "CCar destructor" << endl; }};int main(){ CCar car; return 0;}//輸出結果:CEngine contructorCTyre contructorCCar contructorCCar destructorCTyre destructorCEngine destructor
四、友元(friends)
1、友元分為友元函數和友元類兩種
(1)友元函數 : 一個類的友元函數可以訪問該類的私人成員
class CCar ; //提前聲明 CCar 類,以便後面的CDriver 類使用class CDriver{ public: void ModifyCar( CCar * pCar) ; // 改裝汽車};class CCar{ private: int price; friend int MostExpensiveCar( CCar cars[], int total); // 聲明友元 friend void CDriver::ModifyCar(CCar * pCar); // 聲明友元,可包括構造、解構函式};void CDriver::ModifyCar( CCar * pCar){ pCar->price += 1000; // 汽車改裝後價值增加}int MostExpensiveCar( CCar cars[],int total){ // 求最貴汽車的價格 int tmpMax = -1; for( int i = 0;i < total; ++i ) if( cars[i].price > tmpMax) tmpMax = cars[i].price; return tmpMax;}
(2)友元類 : 如果A 是B的友元類,那麼A 的成員函數可以訪問B的私人成員,友元類之間的關係不能傳遞,不能繼承
class B{ friend class A; // 聲明A為友元類};
五、常量成員函數
1、作用:如果不希望某個對象的值被改變,則定義該對象的時候可以在前面加 const關鍵字
在類的成員函數說明後面可以加const關鍵字,則該成員函數成為常量成員函數。
常量成員函數內部不能改變屬性的值,也不能調用非常量成員函數
在定義常量成員函數和聲明常量成員函數時都應該使用const 關鍵字
class Sample { private : int value; public: Sample() { } void SetValue() { }};const Sample Obj; // 常量對象Obj.SetValue (); //錯誤,常量對象只能使用建構函式、解構函式和有const說明的函數(常量方法)
2、常量成員函數的重載:兩個函數,名字和參數表都一樣,但是一個是const,一個不是,算重載
3、mutable成員變數:
(1)作用:mutable突破const的限制而設定,被mutable修飾的變數將永遠處於可變的轉態,即使在一個const函數中。
(2)應用:如果類的成員函數不會改變對象的狀態,那麼一般會聲明成const。但是,有些時候,需要在const的函數裡面修改一些跟類狀態無關的資料成員,那麼這些資料成員就應該被mutable來修飾。
class CTest{ public: bool GetData() const{ m_n1++; return m_b2; } private: mutable int m_n1; bool m_b2;};