C++静的メンバー変数と静的メンバー関数

5231 ワード

クラスの静的メンバーには、静的メンバー変数と静的メンバー関数の2つがあります.構文は、通常のメンバー変数とメンバー関数の前にstaticキーを追加します.
0、定義
class CRect{
public:
	void show();//      
	static void printTotal();//      
private:
	int width, height;//      
	static int totalNumber;//      
	static int totalArea;//      

};

1、原因がある
静的メンバー変数は本質的にグローバル変数です.オブジェクトが1つも存在しないクラスでも、静的メンバー変数が存在します.静的メンバー関数は、特定のオブジェクトに作用する必要はありません.したがって、本質的にグローバル関数です.静的メンバーを設定する目的は、クラスに密接に関連するグローバル変数とグローバル関数をクラスに書き込むために、形式的に全体となり、カプセル化された効果を達成するためですが、その効果はグローバル変数/関数の定義と同じです.
2、静的メンバー変数/関数の違い
  • 通常のメンバー変数は、各オブジェクトがそれぞれ1部を有し、静的メンバー変数は1部のみであり、すべての同類オブジェクトによって共有される.
  • 通常のメンバー関数は、あるオブジェクトに作用するに違いないが、静的メンバー関数は特定のオブジェクトに作用しない.
  • アクセス方式:通常のメンバーにアクセスする場合、オブジェクト名を通過する.アクセスするメンバー変数がどのオブジェクトに属するか、または呼び出すメンバー関数がどのオブジェクトに作用するかを示すメンバー名.静的メンバーにアクセスする場合は、クラス名::メンバー名でアクセスできます.アクセスされるメンバーがどのオブジェクトに属しているか、またはどのオブジェクトに作用しているかを指定する必要はありません.したがって、クラスの静的メンバーには、まだオブジェクトが生成されていないときにアクセスすることもできます.
  • 占有空間:sizeofを使用してクラスが占有する空間を計算する場合、sizeof(CRectangle)=8のような非静的メンバー変数の値のみが計算され、2つのintタイプのwidthおよびheightが計算されます.
  • パラメータ伝達:通常のメンバー関数はパラメータ伝達時にコンパイラがthisポインタを非表示に伝達する.このポインタによって、呼び出しクラスが生成したオブジェクトを決定します.しかし、静的メンバー関数にはthisポインタがなく、どのオブジェクトのデータにアクセスすべきか分からないため、プログラムでは静的メンバー関数でクラス内の通常の変数にアクセスできません.

  • 3、いくつかの規則
  • オブジェクトとオブジェクトの間のメンバー変数は、互いに独立しています.データを共有するには、静的メンバーと静的メソッドを使用する必要があります.
  • 静的メンバー変数をクラスに宣言すれば、オブジェクトを定義しなくても静的メンバー変数に空間を割り当てることができ、静的メンバー変数を使用することができます.(静的メンバー変数は、オブジェクトが作成される前にメモリ領域が割り当てられているため)
  • 静的メンバー変数はクラスにありますが、オブジェクトの作成に伴って空間を割り当てるものではなく、オブジェクトの取り消しに伴って解放されるものではありません(一般的なメンバーはオブジェクトの作成時に空間を割り当て、オブジェクトの取り消し時に解放されます).静的メンバー変数は、プログラムのコンパイル時に空間を割り当て、プログラムの終了時に空間を解放します.
  • 静的メンバーの定義と宣言には、キーstaticが追加されます.静的メンバーは、次の2つのコロンで使用できます.
  • 静的メンバー変数の初期化は、クラスの外側で行います.初期化のフォーマットは、データ型クラス名::静的メンバー変数名=初期値;
  • パラメータでテーブルを初期化することはできません.静的メンバー変数を初期化します.
  • は、クラス名によって静的メンバー変数を参照してもよいし、オブジェクト名によって静的メンバー変数を参照してもよい.

  • 4、ケース
    例1クラス名でクラスの一般メンバー関数と静的メンバー関数を呼び出す
    #include 
    using namespace std;
    
    class CRect{
    public:
    	void setParam(){}
    	static void show(){}
    };
    
    int main()
    {
    	CRect::setParam();
    	CRect::show();
    
    	return 0;
    }
    

    コンパイルエラー:error C 2352:‘CRect::setParam’:illegal call of non-static member function結論:クラス名でクラスを呼び出すことができない非静的メンバー関数例2クラスのオブジェクトでクラスを呼び出す静的メンバー関数と非静的メンバー関数
    #include 
    using namespace std;
    
    class CRect{
    public:
    	void setParam(){}
    	static void show(){}
    };
    
    int main()
    {
    	CRect crt;
    	crt.setParam();
    	crt.show();
    
    	return 0;
    }
    

    コンパイル結論:クラスのオブジェクトからクラスの静的/非静的メンバー関数を呼び出すことができる例3クラスの静的メンバー関数でクラスの非静的メンバー変数を使用する
    #include 
    using namespace std;
    
    class CRect{
    public:
    	void setParam(){}
    	static void show()
    	{
    		cout<

    コンパイルエラー:error C 2597:illegal reference to data member'CRect::m_width’in a static member functionの理由:静的メンバー関数はクラス全体に属し、クラスインスタンス化オブジェクトの前にスペースが割り当てられているのに対し、クラスの非静的メンバーはクラスインスタンス化オブジェクトの後にメモリ領域がある必要があるため、この呼び出しは変数を宣言していないのに事前に使用するのと同じようにエラーが発生します.結論:クラスの静的メンバー関数でクラスを使用できない非静的メンバー例4クラスの非静的メンバー関数で静的メンバー変数を使用
    #include 
    using namespace std;
    
    class CRect{
    public:
    	void setParam()//                   
    	{
    		m_height = 10;
    		cout<

    コンパイルの結論:クラスの非静的メンバー関数では、静的メンバー変数(明らか)例5を使用してクラスの非静的メンバー関数で静的メンバー関数を呼び出すことができる
    #include 
    using namespace std;
    
    class CRect{
    public:
    	void setParam()
    	{
    		show();
    	}
    	static void show()
    	{
    		cout<

    コンパイルは結論によって:総合例4、5、クラスの非静的メンバー関数の中で静的メンバー変数を使用することもできるし、静的メンバー関数を呼び出すこともできることを知ることができる.すなわち、クラスの非静的メンバー関数はクラスの静的メンバー例6クラスの静的メンバー関数を使用して非静的メンバー関数を呼び出すことができる.
    #include 
    using namespace std;
    
    class CRect{
    public:
    	void setParam()
    	{
    		cout<

    コンパイルエラー:error C 2352:‘CRect::setParam’:illegal call of non-static member function原因:関数を宣言せずに事前に呼び出した結論:総合例3、6では、クラスの静的メンバー関数では非静的メンバー変数を使用できないし、非静的メンバー関数を呼び出すことができない.すなわち、クラスの静的メンバー関数では、非静的メンバーは使用できません.例7クラスの静的メンバー変数の使用
    #include 
    using namespace std;
    
    class CRect{
    public:
    	void setParam()
    	{
    		cout<

    コンパイルエラー:error LNK 2001:unresolved external symbol"private:static int CRect::m_height"(?m_height@CRect@@0 HA)理由:クラスの静的メンバー変数は使用前に初期化されず、クラス外でmain関数外でint CRect::m_height = 0;静的メンバー変数を初期化すると、クラスの静的メンバー変数は初期化してから使用する必要があります.例8クラスの静的メンバー変数の初期化位置
    class CRect{
    public:
    	
    private:
    	static m_height;
    };
    
    int CRect::m_height = 0;//A
    
    int main()
    {
    	int CRect::m_height = 0;//B
    	CRect crt;
    	int CRect::m_height = 0;//C
    	crt.setParam();
    	crt.show();
    
    	return 0;
    }
    

    クラスの静的メンバー変数をA,B,Cの3箇所でそれぞれ初期化した場合、Aのみが初期化が正しく、BとCの初期化コンパイルエラー:error C 2655:‘m_height’:definition or redeclaration illegal in current scope結論:クラスの静的メンバー変数の初期化の位置はクラス外でmain関数の前(理解が間違っていますか?)
    5、参考
    https://www.cnblogs.com/codingmengmeng/p/5906282.html http://c.biancheng.net/view/165.html