?
(一)基本概念:
1、類與對象:
1 //聲明類 2 class Human { 3 4 //... Data members and methods go here 5 6 }; 7 8 //定義對象 9 Human human;
?
2、通常用class聲明類,struct也可以,只不過在信息隱藏機制上有點區別;struct默認是public,而class默認是private;只能在類的成員函數或friend函數中訪問類的非公有成員;
3、成員選擇符:' . ' 和 ' -> ';
4、成員函數的定義:
兩種方式:一種在類內定義,所定義的成員函數都是inline類型的;一種是在類外定義;在類外定義時,要使用 ‘::’ 域解析符,在類外定義成員函數,如果聲明時,使用inline關鍵字,可使在類外定義的成員函數強制變成內聯函數;
1 class Person { 2 3 public : 4 void setAge( unsigned n ); 5 unsigned getAge() const; 6 private : 7 unsigned age; 8 9 }; 10 11 //define class method; 12 13 void Person::setAge( unsigned n ){ 14 age = n; 15 } 16 unsigned Person::getAge(){ 17 return age; 18 }
?
5、效率和健壯性:
(1)通過引用來傳遞和返回對象:
一般來說,對對象的傳遞和返回應該使用“引用”,因為這樣可以提高效率;
注意:在返回引用類型的對象時,如果是在類內定義的對象,要加上static修飾,否則這個對象對其他函數時不可見的;
1 C& get(){ 2 3 static C c1; //注意static修飾符; 4 c1.set(123); 5 return C1; 6 7 }
?
(2)const類型參數的對象引用:
1 class C{ 2 3 public: 4 void setName(const string& n){ name = n; } 5 //通過const的修飾,setName()不會修改n的值; 6 //... other public members; 7 8 priavte: 9 string name; 10 11 };
?
(3)const成員函數:
如果一個成員函數不會直接或間接地改變該函數所屬對象的任何數據成員,最好把這個成員函數標記為const;稱這樣的成員函數為只讀函數;它只能調用其他的const成員函數;
例如:int get() const { ? return num ; ? }
1 //下面展示const的三種用法: 2 3 class C { 4 5 public : 6 //set()中的const表明它不會修改參數n的值; 7 void set (const string& n) { name = n ; } 8 //前面的const表明誰也不能通過這個引用來修改name的值; 9 //第二個const表明get()不會修改name的值; 10 const string& get() const { return name ; } 11 private: 12 string name; 13 14 };
?
?(二)構造函數與析構函數:
?
1、構造函數:主要用來對數據成員進行初始化,并負責在對象創建時需要處理的事務,對類的健壯性有著重要作用;
特點:函數名與類名相同;沒有返回類型;自動調用;可重載;行為與其他函數相同;可在類中定義,也可在聲明之外定義;
(1)約束對象的創建:
如果定義了非默認的構造函數,而沒有定義默認的構造函數,則系統不會提供默認的構造函數;
(2)在類C的構造函數中錯誤的使用單一的C類型參數; 例如: class C { ?public : ?C (C obj);? } //紅色標注的是錯誤的;
在拷貝構造函數可以有一個C參數,但那是一個引用;?例如:class C { ?public :??C (C& obj);? } ? //紅色標注的是正確的,因為它是一個拷貝構造函數;
?
2、拷貝構造函數:
(1)在默認情況下,系統會自動生成一個拷貝構造函數,將源對象所有數據成員的值逐一賦值給目標對象相應的數據成員;
兩種原型:例如:Person( Person& ); ? ? ? ? ? ?Person( const Person& )
(2)自定義拷貝構造函數:第一個以后的參數都必須有默認值;例如:
Person( const Person& p , bool married = false ?);
當一個類包含指向動態存儲空間指針類型的數據成員,則應為這個類設計拷貝構造函數;
//應當舉例說明:::::暫略
?
通過自定義構造函數可禁止通過傳值方式傳遞和返回類對象:因為傳值需要拷貝,把拷貝構造函數設為私有,可禁止傳值;
1 class C { 2 3 public : 4 C(); 5 private: 6 C( C& ); //把拷貝構造函數設為私有; 7 8 }; 9 10 void f( C ) { ... } //Call by value 11 12 C g() { ... } //return by value 13 14 int main() 15 { 16 C c1,c2; 17 f(c1); //...Error,可改為 void f(C& obj) { ... } 18 c2 = g(); //....Error,可改為 C& g(){ ... }; 19 }
?
3、轉型構造函數:只有一個參數,用于類型間的轉換;例如,類C的轉型構造函數可將其他類型的變量轉型為類C類型的變量;
? ? ?注意關鍵字:explicit;
?
4、構造函數初始化程序:
1 //在此程序中,對c進行賦值是非法的.... 2 class C { 3 public : 4 c() { 5 x = 0; 6 c = 0; //Error . c is const 7 } 8 private: 9 int x; 10 const int c; 11 };
應改為:這是初始化const成員變量的唯一方法;初始化列表僅在構造函數中有效;可初始化任何數據成員;
1 class C { 2 public : 3 C() : c( 0 ) { x = 0; } 4 private : 5 int x; 6 const int c; 7 };
?
5、構造函數與操作符new和new[]
當使用動態方式為一個對象分配存儲空間時,C++操作符new和new[]比函數malloc和calloc做的更好, 因為它們會調用相應的構造函數;
?
6、析構函數:
發生在如下情況:一是以某個類作為數據類型的變量超出了其作用范圍;一是用delete操作符刪除動態分配的對象;
例如:~C(); ? ?//不帶參數,不能被重載;
?
7、構造函數與析構函數的調用順序:
構造函數:先調用父類的構造函數,然后才是子類的構造函數;
析構函數:先調用子類的析構函數,然后才是父類的析構函數;
?
(三)類數據成員與類成員函數:
1、使用 ?static ?修飾, 屬于整個類,可被某個對象調用,也可被類調用(被類調用時,使用 :: 操作符);修飾詞一般只在聲明時使用;例如:
1 class C{ 2 3 private : 4 static int x ; 5 6 }; 7 8 int C :: x = 0; //無需加static
?
2、在成員函數內部定義static變量:
該類的所有的對象在調用這個成員函數時,將共享這個變量;
?
(四)指向對象的指針(->):
1、用途:一是作為參數傳遞給函數,或是通過函數返回,一是使用操作符new和new[]動態創建對象,然后返回一個指向該對象的指針;
?
2、常量指針this:在成員函數內部可以用this來訪問與成員函數的調用相關聯的對象;
例如:void setID (const string& id) { ?this->id = id ; ?}?
?
?
?
//// //C++學習筆記 ////