日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

类和对象提高

發布時間:2025/3/12 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 类和对象提高 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

程序設計與算法(三)C++面向對象程序設計-郭煒 第三周
總結整理:
目錄:

      • 1.this指針
      • 2.靜態成員
      • 3.成員對象和封閉類
      • 4.友元 (friends)
      • 5.常量成員函數

1.this指針

C++程序到C程序的翻譯

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

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(); //c1被修改,把c1的值賦值給c2return 0; } //輸出 2,1 class A { int i;public: void Hello() { cout << "hello" << endl; } }; // void Hello(A * this ) { cout << "hello" << endl; } int main() { A * p = NULL; p->Hello(); // Hello(p); } // 輸出:hello-------------------------------------------- class A { int i;public: void Hello() { cout << i << "hello" << endl; } }; // void Hello(A * this )// { cout << this->i << "hello" << endl; } //this若為NULL,則出錯!! 找不到空指針指向的對象的i int main() { A * p = NULL; p->Hello(); // Hello(p); } // 輸出:hello

靜態成員函數中不能使用 this 指針!
因為靜態成員函數并不具體作用與某個對象!
因此,靜態成員函數的真實的參數的個數,就是程序中寫出的參數個數!
類的非靜態成員函數,真實的參數比所寫的參數多1,多出來的是this指針

2.靜態成員

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

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

普通成員變量每個對象有各自的一份,而靜態成員變 量一共就一份,為所有對象共享。
同一個類的不同的對象,普通成員變量不一樣。而靜態成員變量則一樣
sizeof 運算符不會計算靜態成員變量

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

普通成員函數必須具體作用于某個對象,而靜態成員 函數并不具體作用于某個對象。不在一個對象內部,而是放在所有對象外部,為所有對象所共享
因此靜態成員不需要通過對象就能訪問。

靜態成員變量本質上是全局變量,哪怕一個對象都不存在,類 的靜態成員變量也存在。
靜態成員函數本質上是全局函數。
設置靜態成員這種機制的目的是將和某些類緊密相關的全局變量和函數寫到類里面,看上去像一個整體,易于維護和理解。別的類沒法訪問這個變量

如何訪問靜態成員
1) 類名::成員名
CRectangle::PrintTotal();
2) 對象名.成員名
CRectangle r; r.PrintTotal();
3) 指針->成員名
CRectangle * p = &r; p->PrintTotal(); 并不只屬于到p所指向的那個對象
4) 引用.成員名
CRectangle & ref = r; int n = ref.nTotalNumber

靜態成員示例
考慮一個需要隨時知道矩形總數和總面積的圖形 處理程序
可以用全局變量來記錄總數和總面積
用靜態成員將這兩個變量封裝進類中,就更容易 理解和維護

#include<iostream> using namespace std; 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_; nTotalNumber ++; nTotalArea += w * h; } CRectangle::~CRectangle(){ nTotalNumber --; nTotalArea -= w * h; } void CRectangle::PrintTotal() { cout << nTotalNumber << "," << nTotalArea << endl; }int CRectangle::nTotalNumber = 0; int CRectangle::nTotalArea = 0; // 必須在定義類的文件中對靜態成員變量進行一次說明//或初始化。否則編譯能通過,鏈接不能通過。 int main() { CRectangle r1(3,3), r2(2,2); //cout << CRectangle::nTotalNumber; // Wrong , 私有 CRectangle::PrintTotal();r1.PrintTotal(); return 0; }//輸出結果: //2,13//2,13

此CRectangle類寫法, 有何缺陷?
在使用CRectangle類時,有時會調用復制構造函數 生成臨時的隱藏的CRectangle對象
調用一個以CRectangle類對象作為參數的函數時,
調用一個以CRectangle類對象作為返回值的函數時
臨時對象在消亡時會調用析構函數,減少nTotalNumber 和 nTotalArea的值,可是這些臨時對象在生成時卻沒有增加 nTotalNumber 和 nTotalArea的值,因此最終可能數量小于應有的。
解決辦法:為CRectangle類寫一個復制構造函數

CRectangle :: CRectangle(CRectangle & r ) {w = r.w; h = r.h; nTotalNumber ++; nTotalArea += w * h; }

在靜態成員函數中,不能訪問非靜態成員變量, 也不能調用非靜態成員函數。非靜態成員函數可能需要調用非靜態成員變量,那不能確定是哪一個非靜態成員變量,因此不能

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

3.成員對象和封閉類

有成員對象的類叫 封閉(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 的初始化沒問題,用 默認構造函數即可。
任何生成封閉類對象的語句,都要讓編譯器明白,對象中的成員對象,是如何 初始化的。
具體的做法就是:通過封閉類的構造函數的初始化列表。
成員對象初始化列表中的參數可以是任意復雜的表達式,可以包括函數,變量 ,只要表達式中的函數或變量有定義就行。

封閉類構造函數和析構函數的執行順序
封閉類對象生成時,先執行所有對象成員的構造函數,然后才執 行封閉類的構造函數。
對象成員的構造函數調用次序和對象成員在類中的說明次序一致 ,與它們在成員初始化列表中出現的次序無關。
當封閉類的對象消亡時,先執行封閉類的析構函數,然后再執行 成員對象的析構函數。次序和構造函數的調用次序相反。

封閉類實例

#include<iostream> using namespace std;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 contructor //CTyre contructor //CCar contructor //CCar destructor //CTyre destructor //CEngine destructor

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

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 **/

4.友元 (friends)

友元分為友元函數和友元類兩種

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; } int main() { return 0; }

可以將一個類的成員函數(包括構造、析構函數)說明為另一個類的友元。

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

2)友元類: 如果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的友元類, //故此處可以訪問其私有成員 }; int main(){ return 0; }

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

5.常量成員函數

如果不希望某個對象的值被改變,則定義該對象的時候可以在前面加 const關鍵字。

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

在類的成員函數說明后面可以加const關鍵字,則該成員函數成為常量 成員函數。
常量成員函數內部不能改變屬性的值,也不能調用非常量成員函數

class Sample { private : int value; public: void func() { }; Sample() { } void SetValue() const { value = 0; // wrong func(); //wrong } }; const Sample Obj; Obj.SetValue (); //常量對象上可以使用常量成員函數

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

class Sample { private : int value; public: void PrintValue() const; }; void Sample::PrintValue() const { //此處不使用const會 //導致編譯出錯 cout << value; } void Print(const Sample & o) { o.PrintValue(); } //若 PrintValue非const則編譯錯

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

常量成員函數的重載

兩個函數,名字和參數表都一樣,但是一個是const,一個不是,算重載。

#include <iostream> using namespace std;class CTest { private : int n; public: CTest() { n = 1 ; } int GetValue() const { return n ; } int GetValue() { return 2 * n ; } };int main() {const CTest objTest1;CTest objTest2; cout << objTest1.GetValue() << "," << objTest2.GetValue() ; return 0; } //1,2

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

class CTest { public: bool GetData() const { m_n1++; return m_b2; } private: mutable int m_n1; bool m_b2; }; 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的类和对象提高的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。