類是C++的一個重要概念,也是面向對象的一個重要內容。類的行爲相似結構體,但功能比結構體的更強大。類是定義該類對象的一個模板,它告訴咱們,一個類應該具備什麼內容。java
類用關鍵字class
聲明、定義。函數
class LiF1; // 聲明一個類 class LiF2 {}; // 聲明並定義一個類
若是僅做聲明,在聲明以後定義以前,它是一個不徹底類型,這時只能定義指向該類型的指針或引用,能夠聲明但不能定義以該類型做爲參數或返回值的函數。在類的名字出現以後,他就被認爲是聲明過的,所以,能夠在類內定義指向自身類型的指針或引用。有時會遇到一些比較複雜的情形,就須要咱們先聲明一個類,隨後再去完善定義。好比:咱們須要一個類X包含一個指向類Y的指針,同時,類Y又包含一個類型爲X的對象,實現以下:this
class X; class Y { X* x; }; class X { Y y; };
類內的數據稱爲類的成員(member),成員包括成員變量和成員函數。成員變量定義類的屬性,成員函數定義類的行爲。指針
在類內聲明的變量稱爲成員變量。成員變量能夠是任何數據類型,甚至能夠是指向自身類型的指針或引用。code
聲明在類內部的函數稱爲成員函數。成員函數的本質也是普通函數,只是編譯器幫咱們在成員函數的形參列表首部隱式加上了一個指向該類型的指針,即要求該類的對象才能調用。而在調用的時候,編譯器也爲咱們在實參列表加入了this
指針,即指向函數調用對象自己的指針。對象
class LiF { public: void doNothing(){} // 實際的定義是:void doNothing(LiF *this){} }; LiF lif; lif.doNothing(); // 實際的調用是:doNothing(this);
在類內,咱們能夠經過訪問權限限定符public
、protected
、private
限制類內成員的訪問權限。同一個訪問限定符能夠出現屢次,默認狀態下,在第一個訪問限定符出現以前,類內的訪問權限是private
,在最後一個訪問限定符出現以後,全部成員的訪問權限都是限定符指定的權限等級。繼承
class LiF { int a; // a是默認的private權限 public: int b(); // b()在public限定符下,因此是public權限 protected: int c; // c在protected限定符下,因此是protected權限 private: int d; // d在private限定符下,因此是private權限 public: // 容許同一限定符重複出現 int e; };
對應的權限以下:內存
public
:能夠被類的成員函數、友元、子類的成員函數和友元、類的對象訪問;能夠被子類以任何方式繼承。protected
:能夠被類的成員函數、友元函數、子類的成員函數和友元訪問,類的對象無權訪問;能夠被子類以任何方式繼承。private
:只能被類的成員函數、友元訪問;沒法經過任何方式繼承。與java、C#不一樣的是,C++限定符的限制對象是類,而非類的對象;C++的類也沒有訪問權限之分。編譯器
class LiF { public: static int sum(const LiF& l1, const LiF& l2) { return l1.lif + l2.lif; // 能夠直接訪問對象的私有成員 } private: int lif; }; LiF l1, l2; LiF::sum(l1, l2);
爲了更高效地利用內存,C++採用數據和方法分離的存儲方法。即在咱們定義類時,程序會爲這個類劃分一個區域,專門存放這個類的成員函數;而在咱們每次定義該類的對象時,程序會按照類的定義爲每個對象都分配一段內存,存儲對象數據。也正所以,C++隱式使用對象指針訪問成員函數,也出現了this
指針。編譯
對象佔用的內存大小由成員變量佔用的內存決定。特殊地,若是在類內包含了其餘類的對象,那麼內存佔用會計入被包含對象的大小;若是隻是包含其餘類的指針,那麼就只增長一個指針的佔用。若是在類內聲明瞭虛函數,那麼須要額外增長4個字節,用於存儲虛函數表指針。
class LiF1 {}; sizeof(LiF1); // 結果爲1,這是由於這個類沒有包含任何數據成員,因此僅僅分配1個字節用於標記類 class LiF2 { public: void doNothing(){} private: int lif; }; sizeof(LiF2); // 結果爲4,即sizeof(int) class LiF3 { public: virtual void doSomething() = 0; }; sizeof(LiF3); // 結果爲4,這時有虛函數表指針做爲類的標記,因此不須要額外的1個字節 class LiF4 { public: virtual void doSomething() = 0; private: int lif; }; sizeof(LiF4); // 結果爲8,即int的大小+虛函數表指針的大小 class LiF5 { private: int a, b; }; class LiF6 { private: LiF5 lif5; }; sizeof(LiF6); // 結果爲8,即sizeof(LiF5) class LiF7 { private: LiF5 *lif5; }; sizeof(LiF7); // 結果爲4,即sizeof(LiF5*)
爲了提升存取效率,類的成員變量都是按4字節對齊的。不滿4字節的能夠合併,超過4字節的只能另起4字節。
class l1 { char a; char b; int c; }; class l2 { char a; int c; char b; }; sizeof(l1); // 結果爲8 sizeof(l2); // 結果爲12