【c++】静的メンバー変数と静的メンバー関数|メンバーオブジェクトと閉じたクラス

16550 ワード

静的メンバー変数と静的メンバー関数
説明の前にstaticキーワードを付けたメンバー.通常のメンバー変数は各オブジェクトに1部ずつあり、静的メンバー変数は全部で1部であり、すべてのオブジェクトに共有されます.sizeof演算子は静的メンバー変数を計算しません.通常のメンバー関数はオブジェクトに具体的に作用する必要がありますが、静的メンバー関数はオブジェクトに具体的に作用しません.静的メンバーは、オブジェクトを介してアクセスする必要はありません.静的メンバーへのアクセス方法:1)クラス名::メンバー名CRectangle::PrintTotal();2)対象名メンバー名CRectangle r;r.PrintTotal(); 3)ポインタ->メンバー名CRectangle*p=&r;p->PrintTotal(); 4)引用.メンバー名CRectangle&ref=r;int n = ref.nTotalNumber; 静的メンバー変数は本質的にグローバル変数であり、1つのオブジェクトが存在しなくてもクラスの静的メンバー変数が存在します.静的メンバー関数は本質的にグローバル関数です.静的メンバーを設定するという究極の目的は、クラス全体のように見え、メンテナンスと理解が容易なグローバル変数と関数をクラスに書き込むことです.
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;
}

静的メンバー関数では、非静的メンバー変数にアクセスしたり、非静的メンバー関数を呼び出したりすることはできません.
void CRectangle::PrintTotal()
{
cout << w << "," << nTotalNumber << "," << nTotalArea << endl; //wrong
}
CRetangle::PrintTotal(); //    ,w           ?

ただし、上記のように欠陥があり、CRectangleクラスを使用する場合、レプリケーションコンストラクタを呼び出して一時的に非表示のCRectangleオブジェクトを生成するCRectangleクラスオブジェクトをパラメータとする関数を呼び出したときにCRectangleクラスオブジェクトを戻り値とする関数を呼び出したときに、このときコンストラクタを呼び出していないため、数は+、ただし、非表示のCRectangleオブジェクトが消滅すると、構造関数が呼び出されます.これにより、レプリケーション構造関数を書くことができます.
メンバー・オブジェクトと閉じたクラス
≪メンバー・オブジェクト|Member Objects|ldap≫:クラスのメンバー変数が別のクラスのオブジェクトで、メンバー・オブジェクトを含むクラスを閉じたクラス(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;//errorコンパイルエラー•コンパイラはcarを知らない.tyreはどのように初期化•car.Engineの初期化に問題はありません:デフォルトの構造関数で
閉じたクラスのコンストラクション関数を定義する場合、初期化リストを追加します.クラス名::コンストラクション関数(パラメータテーブル):メンバー変数1(パラメータテーブル)、メンバー変数2(パラメータテーブル)...{}メンバーオブジェクト初期化リストのパラメータ•任意の複雑な式•関数/変数/式の関数、変数に定義があります
閉じたクラスオブジェクトが生成すると、•S 1:すべてのメンバーオブジェクトのコンストラクション関数を実行•S 2:閉じたクラスのコンストラクション関数メンバーオブジェクトのコンストラクション関数呼び出し順序を実行•クラス内のメンバーオブジェクトの説明順序と一致•メンバー初期化リストに表示される順序に関係なく閉じたクラスのオブジェクトが消滅した場合•S 1:閉じたクラスのコンストラクション関数を先に実行•S 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 contructor CTyre contructor CCar contructor CCar destructor CTyre destructor CEngine destructor