C++面向對象程序設計(三)——3.類和對象提高

      網友投稿 913 2025-03-31

      C++面向對象程序設計(三)——3.類和對象提高

      本文是中國大學MOOC,北京大學程序設計與算法(三)C++面向對象程序設計第三周筆記。本課程學習的github倉庫歡迎Fork

      本文目錄

      C++面向對象程序設計(三)——3.類和對象提高

      一 this 指針

      C++ 到 C程序的翻譯

      二 靜態成員

      基本概念

      如何訪問靜態成員

      1.類型::成員名

      2.對象名.成員名

      3.指針->成員名

      4.引用.成員名

      三 成員對象和封閉類

      基本概念

      封閉類構造函數和析構函數的執行順序

      四 友元

      友元函數

      友元類

      五 常量成員函數

      六 mutable成員變量

      一 this 指針

      C++ 到 C程序的翻譯

      //C++ class CCar{ public: int price; void SetPtice(int p); }; void CCar::SetPrice( int p ){ price = p; } int main(){ CCar car; car.SetPrice( 20000 ); return 0; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      //C struct CCar{ int price; }; void SetPrice( struct CCar * this, int p) { this -> price = p; } int main(){ struct CCar car; SetPrice( & car, 20000 ); return 0; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      對比一下這兩個程序,我們可以看到:

      每個類的非靜態成員函數中都隱含包含一個this指針,類型為當前類類型的指針類型

      this 作用就是指向成員函數所作用的對象。在非靜態成員函數中可以直接使用this來代表指向該函數作用的對象的指針。

      我們可以看一個案例:

      class Complex{ public: double real,imag; void Print(){ cout << real << "," << imag; } Complex( double r, double i ):real( r ),imag( i ) {} Complex AddOne(){ this -> real ++; //等價于 real++ this -> Print(); //等于于 Print return * this; } }; int main(){ Complex c1(1,1),c2(0,0); c2 = c1.AddOne(); return 0; }//輸出 2,1

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      需要注意的是:

      靜態成員函數中不能使用this指針,因為靜態成員函數并不具體作用于某個對象。所以,靜態成員函數的真實參數的個數,就是程序中寫出的參數個數。

      然而,類的非靜態成員函數,真實的參數比所寫的參數多1,多的這個就是this指針。

      二 靜態成員

      基本概念

      在定義前面加了static關鍵字的成員

      class CRectangle { private: int w, h; static int nTotalArea; //靜態成員變量 static int nTotalNumber; public: CRectangle(int w_, int h_); ~CRectangle(); static void PrintTotal(); //靜態成員函數 };

      1

      2

      3

      4

      5

      6

      C++面向對象程序設計(三)——3.類和對象提高

      7

      8

      9

      10

      11

      靜態成員變量為所有對象共享,且sizeof運算符不會計算靜態成員變量

      class CMyclass{ int n; static int s; }; //sizeof(CMyclass) 等于 4

      1

      2

      3

      4

      5

      普通成員變量每個對象有各自的一份,而靜態成員變量一共就一份,為所有對象共享

      普通成員函數必須具體作用于某個對象,而靜態成員函數并不具體作用于某個對象。所以實際上靜態成員不需要通過對象就能訪問。

      如何訪問靜態成員

      CRectangle::PrintTotal();

      1

      CRectangle r; r.PrintTotal();

      1

      2

      CRectangle * p = &r; p -> PrintTotal();

      1

      2

      CRectangle & ref = r; int n = ref.nTotalNumber;

      1

      2

      靜態成員變量本質上是全局變量,哪怕一個對象都不存在,類的靜態成員變量也存在

      靜態成員函數本質上是全局函數,主要目的是將和某些類緊密相關的全局變量和函數寫到類里面,看上去想一個整體,易于維護和理解

      class CRectangle { private: int w, h; static int nTotalArea; //靜態成員變量 static int nTotalNumber; public: CRectangle(int w_, int h_); ~CRectangle(); static void PrintTotal(); //靜態成員函數 }; CRectangle::CRectangle(int w_,int h_ ) { w = w_; h = h_; nTotalNmuber ++; nTotalArea += w * h; } CRectangle::~CRectangle() { nTotalNumber --; nTotalArea -= w * h; } void CRectangle::PrintTotal() { cout << nTotalNumber << "," <

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      要注意的是:在靜態成員函數中,不能訪問非靜態成員變量,也不能調用非靜態成員函數

      必須在類外面對靜態函數變量進行說明或初始化

      void CRectangle::PrintTotal() { cout << w << "," << nTotalNumber << "," << nTotalArea << endl; //error } CRectangle::PrintTotal(); //解釋不通,w到底屬于哪個對象?

      1

      2

      3

      4

      5

      三 成員對象和封閉類

      基本概念

      有成員對象的類叫封閉類

      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 yre; 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; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      上面的例子中,如果CCar類不定義構造函數,那么下面的語句編譯會出錯

      CCar car;

      因為編譯器不明白car.type,該如何初始化。car.engine的初始化沒問題,用默認構造函數就可以了。

      任何生成封閉類對象的語句,都要使得編譯器明白,對象中的成員對象,是如何初始化的。完成這一任務的方法是通過封閉類的構造函數的初始化列表,成員對象初始化列表中的參數可以是任意復雜的表達式,可以包括函數,變量,只要表達式中的函數或變量有定義就行。

      封閉類構造函數和析構函數的執行順序

      封閉類對象生成時,先所有成員對象的構造函數,然后才執行封閉類的構造函數

      對象成員的構造函數調用次序和對象成員在類中的說明次序一致,與成員初始化列表次序無關

      封閉類對象消亡時,先執行封閉類析構函數,再執行成員對象的析構函數。次序和構造函數的調用次序相反

      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 constructor" << endl;} ~CCar(){ cout << "CCar destructor" << endl;} } int main(){ CCar car; return 0; } //輸出結果 //CEngine contructor //Ctyre contructor //CCar constructor //CCar destructor //Ctyre destructor //CEngine destructor

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      封閉類的對象如果用默認復制構造函數初始化,那么它包含的成員對象也會用復制構造函數初始化

      class A{ public: A(){cout << "default" << endl;} A(A & a){ cout << "Copy" << endl;} }; class B {A a;}; int main(){ B b1, b2(b1); return 0; } //輸出: //default //Copy //b2.a是用類A的復制構造函數初始化的。 //調用復制構造函數的實參是b1.a

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      四 友元

      友元函數

      一個類的友元函數可以訪問該類的私有成員

      class CCar; 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(car[i].price > tmpMax) tmpMax = cars[i].price; } return tmpMax; } int main(){ return 0; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      當然我們還可以把一個類的成員函數(包括析構,構造等)說明為另一個類的友元

      class B{ public: void function(); }; class A{ friend void B::function(); }

      1

      2

      3

      4

      5

      6

      7

      8

      友元類

      如果A是B的友元類,那么A的成員函數可以訪問B的私有成員

      class CCar{ private: int price; friend class CDriver; //聲明CDriver為友元類 }; class CDriver{ public: CCar myCar; void ModifyCar(){ //改裝汽車 myCar.price += 1000; //CDriver是CCar的友元類,所以可以訪問CCar的私有成員 } }; int main(){ return 0; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      友元類之間的關系不能傳遞,不能繼承

      五 常量成員函數

      如果不希望某個對象的值被改變,那么可以在對象前加const關鍵字

      class Sample{ private: int value; public: Sample(){} void SetValue(){} }; const Sample Obj; //常量對象 Obj.SetValue (); //錯誤,常量對象只能使用構造函數,析構函數,有const說明的函數

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      類的成員函數說明后面可以加const關鍵字,該成員函數成為常量成員函數

      常量成員函數內部不能改變屬性的值,也不能調用非常量成員函數

      在定義和聲明成員函數時都應該用const關鍵字

      如果一個成員函數中沒有調用非常量成員函數,也沒有修改成員函數變量的值,那么最好將其寫成常量成員函數

      如果兩個函數,名字參數表都一樣,但是一個有const,一個沒有,算重載

      六 mutable成員變量

      可以在const成員函數中修改的成員變量

      class CTest{ public: bool GetData() const { m_n1++; return m_b2; } private: mutale int m_n1; bool m_b2; };

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      C++ 面向對象編程

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:word換行后前面空出一大段怎么辦(word表格中換行后空出一大段)
      下一篇:文件出現這種情況,是怎么設置的,怎么取消(文檔中設置格式一直顯示怎么取消)
      相關文章
      亚洲综合视频在线| 久久久久久久尹人综合网亚洲| 亚洲一区中文字幕久久| 国产亚洲成av人片在线观看| 中文字幕一精品亚洲无线一区| av在线亚洲欧洲日产一区二区| 亚洲精品动漫人成3d在线| 亚洲国产精品第一区二区三区| 亚洲av区一区二区三| 亚洲国产精品碰碰| 亚洲一区二区精品视频| 国产成人毛片亚洲精品| 亚洲热妇无码AV在线播放| 国产亚洲色婷婷久久99精品| 国产av天堂亚洲国产av天堂| 久久久综合亚洲色一区二区三区| 久久精品国产亚洲| 亚洲综合一区二区精品久久| 亚洲国产人成在线观看| 中文字幕在线日亚洲9| 亚洲av成人一区二区三区观看在线 | 国产AV无码专区亚洲AV漫画| 亚洲午夜未满十八勿入网站2| 久久亚洲综合色一区二区三区| 久久精品国产亚洲AV麻豆~| 亚洲高清视频免费| 亚洲色欲色欲www| 亚洲AV永久无码天堂影院| 亚洲精品国产福利一二区| 国内精品99亚洲免费高清| 亚洲AV午夜成人片| 亚洲精品美女久久久久9999| 77777亚洲午夜久久多喷| 亚洲av无码一区二区三区四区| 亚洲精品国产V片在线观看| 国产V亚洲V天堂无码久久久| 亚洲美女在线观看播放| 亚洲一卡2卡三卡4卡无卡下载| 国产成人va亚洲电影| 亚洲香蕉网久久综合影视| 久久久久亚洲av无码专区|