1. 程式人生 > >C++中成員變數加上static或const關鍵字後的分析

C++中成員變數加上static或const關鍵字後的分析

C++中類成員變數加上static或const關鍵字後的初始化問題。在一個簡單的C++類中定義如下這些變數:

#include <iostream>

using namespace std;

class TestVariable{
	public:
	TestVariable(){}
	private:
	int intVariable;//情況0 不加限定符,這個不需要進行討論
	const int constIntVariable;//情況1 const常量
	static int staticIntVariable;//情況2 靜態變數
	static const int staticConstIntVariable;//情況3 靜態常整型型別
	static const float staticConstNotIntVariable;//情況4 靜態非常整型型別
};

int main(){
	TestVariable variable;
	return 0;

}
加入限定符後多了4中情況,下面就這四種情況分別進行分析。

情況1:const修飾

編譯上面的程式碼,首先在情況1處出現問題,在g++中的錯誤提示是:


在vs中的提示更明顯,“error C2758: “TestVariable::constIntVariable”: 必須在建構函式基/成員初始值設定項列表中初始化”。直接給出瞭解決方法,就是說對於類中的const常量型別而言,需要在建構函式初始化化列表中進行初始化

#include <iostream>

using namespace std;

class TestVariable{
public:
	TestVariable()<span style="color:#ff0000;">:constIntVariable(0)</span>{}
private:
	int intVariable;//情況0 不加限定符,這個不需要進行討論
	const int constIntVariable;//情況1 const常量
	static int staticIntVariable;//情況2 靜態變數
	static const int staticConstIntVariable;//情況3 靜態常整型型別
	static const float staticConstNotIntVariable;//情況4 靜態非常整型型別
};

int main(){
	TestVariable variable;
	return 0;

}
這樣情況1的問題就解決了。

情況2:static修飾

然後編譯上面的程式碼能通過,不過明顯還有問題,就是static變數沒有初始化化,但是編譯時沒有出錯。原因就是還沒有使用到這些變數,因為static變數是類的所有例項共享的,所以在構造variable這個變數時只對constIntVariable這個變數進行了檢查,在編譯時會出錯,但是其餘的3個靜態變數由於沒有使用所有還看不出問題所在。將程式碼修改成這樣來檢查情況2中靜態變數的問題:

#include <iostream>

using namespace std;

class TestVariable{
	public:
	TestVariable():constIntVariable(0){}

	<span style="color:#ff0000;">void printStaticInt(){
		cout<<"staticIntVariable:"<<staticIntVariable<<endl;
	}</span>
	private:
	int intVariable;//情況0 不加限定符,這個不需要進行討論
	const int constIntVariable;//情況1 const常量
	static int staticIntVariable;//情況2 靜態變數
	static const int staticConstIntVariable;//情況3 靜態常整型型別
	static const float staticConstNotIntVariable;//情況4 靜態非常整型型別
};

int main(){
	TestVariable variable;
	variable.printStaticInt();
	return 0;

}
g++編譯時的錯誤情況如下:



vs中的錯誤提示為“error LNK2001: 無法解析的外部符號 "private: static int TestVariable::staticIntVariable" ([email protected]@@0HA)”,這種情況下g++中的提示更明顯些,就是對TestVariable::staticIntVariable這個變數未定義的引用,所以我們的解決方法就是將它初始化。這個變數的初始化這樣操作:

#include <iostream>

using namespace std;

class TestVariable{
	public:
	TestVariable():constIntVariable(0){}

	void printStaticInt(){
		cout<<"staticIntVariable:"<<staticIntVariable<<endl;
	}
	private:
	int intVariable;//情況0 不加限定符,這個不需要進行討論
	const int constIntVariable;//情況1 const常量
	static int staticIntVariable;//情況2 靜態變數
	static const int staticConstIntVariable;//情況3 靜態常整型型別
	static const float staticConstNotIntVariable;//情況4 靜態非常整型型別
};
<span style="color:#ff0000;">int TestVariable::staticIntVariable=1;</span>
int main(){
	TestVariable variable;
	variable.printStaticInt();
	return 0;

}

注意int TestVariable::staticIntVariable=1;這行程式碼不能寫成static int TestVariable::staticIntVariable=1;,否則就在g++中會出現這個錯誤:


而在vs中會出現“error C2720: “TestVariable::staticIntVariable”: 成員上的“static ”儲存類說明符非法”這個錯誤提示。

情況3:static const修飾的整型資料

然後就是情況3和情況4,情況3和情況4中的限定符是一樣的,就是static const(這裡寫成static const和const static好像都可以,最起碼在vs和g++中測試都通過了),不同的是資料型別而已,這裡int型別是一種特例,就是靜態常量整型(short ,int ,long,long long)資料可以在類中初始化,而其他型別都只能在類外面進行初始化。

首先新增呼叫這個變數的函式:

#include <iostream>

using namespace std;

class TestVariable{
	public:
	TestVariable():constIntVariable(0){}

	void printStaticInt(){
		cout<<"staticIntVariable:"<<staticIntVariable<<endl;
	}

	<span style="color:#ff0000;">void printStaticConstInt(){
		cout<<"staticOnstIntVariable:"<<staticConstIntVariable<<endl;
	}</span>
	private:
	int intVariable;//情況0 不加限定符,這個不需要進行討論
	const int constIntVariable;//情況1 const常量
	static int staticIntVariable;//情況2 靜態變數
	static const int staticConstIntVariable;//情況3 靜態常整型型別
	static const float staticConstNotIntVariable;//情況4 靜態非常整型型別
};
 int TestVariable::staticIntVariable=1;
int main(){
	TestVariable variable;
	variable.printStaticInt();
	variable.printStaticConstInt();
	return 0;

}

在g++中編譯的結果為:

用vs編譯出錯:“ error LNK2001: 無法解析的外部符號 "private: static int const TestVariable::staticConstIntVariable" ([email protected]@@0HB)”,和情況2的錯誤提示是一樣的。

只是它的定義方式有兩種,在類內定義:

#include <iostream>

using namespace std;

class TestVariable{
	public:
	TestVariable():constIntVariable(0){}

	void printStaticInt(){
		cout<<"staticIntVariable:"<<staticIntVariable<<endl;
	}

	void printStaticConstInt(){
		cout<<"staticOnstIntVariable:"<<staticConstIntVariable<<endl;
	}
	private:
	int intVariable;//情況0 不加限定符,這個不需要進行討論
	const int constIntVariable;//情況1 const常量
	static int staticIntVariable;//情況2 靜態變數
	<span style="color:#ff0000;">static const int staticConstIntVariable=3;//情況3 靜態常整型型別</span>
	static const float staticConstNotIntVariable;//情況4 靜態非常整型型別
};
 int TestVariable::staticIntVariable=1;
int main(){
	TestVariable variable;
	variable.printStaticInt();
	variable.printStaticConstInt();
	return 0;

}
在類外面定義:
#include <iostream>

using namespace std;

class TestVariable{
	public:
	TestVariable():constIntVariable(0){}

	void printStaticInt(){
		cout<<"staticIntVariable:"<<staticIntVariable<<endl;
	}

	void printStaticConstInt(){
		cout<<"staticOnstIntVariable:"<<staticConstIntVariable<<endl;
	}
	private:
	int intVariable;//情況0 不加限定符,這個不需要進行討論
	const int constIntVariable;//情況1 const常量
	static int staticIntVariable;//情況2 靜態變數
	static const int staticConstIntVariable;//情況3 靜態常整型型別
	static const float staticConstNotIntVariable;//情況4 靜態非常整型型別
};
 int TestVariable::staticIntVariable=1;
<span style="color:#ff0000;"> const int TestVariable::staticConstIntVariable=3;</span>
int main(){
	TestVariable variable;
	variable.printStaticInt();
	variable.printStaticConstInt();
	return 0;

}
注意,這裡const這個關鍵字也需要,否則在g++中會出現這種錯誤提示:它會把它當成一個新的變數,但這個變數和原來的const型別的變數名相同,所以會出錯。



在vs中的提示為:“error C2373: “staticConstIntVariable”: 重定義;不同的型別修飾符”。

情況4:static const修飾的非整型資料

然後就是情況4,對於靜態常量非整型資料而言,如果在類內進行初始化:

#include <iostream>

using namespace std;

class TestVariable{
	public:
	TestVariable():constIntVariable(0){}

	void printStaticInt(){
		cout<<"staticIntVariable:"<<staticIntVariable<<endl;
	}

	void printStaticConstInt(){
		cout<<"staticOnstIntVariable:"<<staticConstIntVariable<<endl;
	}
	void printStaticConstNotIntVariable(){
		cout<<"staticConstNotIntVariable:"<<staticConstNotIntVariable<<endl;
	}
	private:
	int intVariable;//情況0 不加限定符,這個不需要進行討論
	const int constIntVariable;//情況1 const常量
	static int staticIntVariable;//情況2 靜態變數
	static const int staticConstIntVariable;//情況3 靜態常整型型別
	<span style="color:#ff0000;">static const float staticConstNotIntVariable=4.0;//情況4 靜態非常整型型別</span>
};
 int TestVariable::staticIntVariable=1;
 const int TestVariable::staticConstIntVariable=3;
int main(){
	TestVariable variable;
	variable.printStaticInt();
	variable.printStaticConstInt();
	variable.printStaticNotIntVariable();
	return 0;

}
在g++中沒有問題:

在vs 2008中會出現這個錯誤“error C2864: “TestVariable::staticConstNotIntVariable”: 只有靜態常量整型資料成員才可以在類中初始化”。

所以最好還是不要寫這種程式碼吧。

將變數的初始化放在類外面和情況3一樣就可以了:

#include <iostream>

using namespace std;

class TestVariable{
public:
	TestVariable():constIntVariable(0){}

	void printStaticInt(){
		cout<<"staticIntVariable:"<<staticIntVariable<<endl;
	}

	void printStaticConstInt(){
		cout<<"staticOnstIntVariable:"<<staticConstIntVariable<<endl;
	}
	void printStaticConstNotIntVariable(){
		cout<<"staticConstNotIntVariable:"<<staticConstNotIntVariable<<endl;
	}
private:
	int intVariable;//情況0 不加限定符,這個不需要進行討論
	const int constIntVariable;//情況1 const常量
	static int staticIntVariable;//情況2 靜態變數
	static const int staticConstIntVariable;//情況3 靜態常整型型別
	static const float staticConstNotIntVariable;//情況4 靜態非常整型型別
};
int TestVariable::staticIntVariable=1;
const int TestVariable::staticConstIntVariable=3;
<span style="color:#ff0000;">const float TestVariable::staticConstNotIntVariable=4.0;</span>
int main(){
	TestVariable variable;
	variable.printStaticInt();
	variable.printStaticConstInt();
	variable.printStaticConstNotIntVariable();
	return 0;

}

這種情況在g++中和vs中執行的結果就都是正確的了。

最後關於static,它在類中和在類外使用時有不同的含義,這裡總結一下:

1.函式體內的static變數的作用範圍為該函式體,不同於auto變數,該變數的記憶體只能被分配一次,因此其值在下次呼叫時仍維持上次的值。

2.在模組內的static全域性變數可以被模組內的所有函式訪問,但不能被模組外其它函式訪問。

3.在模組內的static函式只可能被這一模組內的其它函式呼叫,這個函式的使用範圍被限定在宣告它的模組內。

4.在類中的static成員變數屬於整個類所擁有,對類的所有物件只有一份拷貝。

5.在類中的static成員函式屬於整個類所擁有,這個函式不接受this指標,因此只能訪問類的static成員變數。

相關推薦

C++成員變數加上staticconst關鍵字分析

C++中類成員變數加上static或const關鍵字後的初始化問題。在一個簡單的C++類中定義如下這些變數: #include <iostream> using namespace std; class TestVariable{ public: Te

沒有躲過的坑--類的靜態成員變數static or const static

工作中是這樣的,A類中有一個成員變數x,最開始宣告為私有: class A{ private: int x; }; 現在需要在另一個cpp中使用這個x,所以要把它變為共有並且靜態: class A{ public: static int

C++成員變數 父類 子類構造析構順序

c++中物件都是先構造成員變數,再呼叫自身的建構函式;故父類成員變數首先被構造,然後呼叫父類的建構函式,再構造子類的成員變數,最後呼叫子類的建構函式。 物件析構時與構造順序相反,子類先呼叫自身的解構函式,再呼叫子類成員變數的解構函式,再呼叫父類的解構函式,再析構父類的成員變

C++ static成員變數static成員函式

最近在做一個服務端的小專案這個專案要用到asio::streambuf這個物件。但是這個類的複製建構函式是私有的也就是導致了它不可以被複制構造。在傳引數的時候就比較不方便,不夠由於它是緩衝區,如果設定多個出現也是不方便。 現在就想做一個static的streambuf,但是希望它是私有的,這樣比

Cpp -C++類成員變數的初始化總結

1. 普通的變數: 一般不考慮啥效率的情況下 可以在建構函式中進行賦值。考慮一下效率的可以再建構函式的初始化列表中進行。 class CA { public: int data; public: CA(); };

C變數 const的應用

const int a=3       表示a被定義為一個整型變數,指定其值為3,而且在變數存在期間其值不能改變。      常變數與常量的異同是:常變數具有變數的基本屬性:有型別,站儲存單元,只是不允許改變其值。可以說,常變數是有

C#學習筆記之六 類定義static關鍵字的用法暨C#靜態變數的意義與使用

<span style="font-size:18px;">using System; namespace MakeoutStatic { class Counter { public static int num; public void clear() { num = 0;

C++類成員變數的初始化總結

class CA { public: int data; …… public: CA(); …… }; CA::CA():data(0)//……#1……初始化列表方式 { //data = 0;//……#1……賦值方式 }; 2、static靜態變數: static變

C/C++staticconst關鍵字的作用總結

static 關鍵字至少有下列 n 個作用:   (1)函式體內 static 變數的作用範圍為該函式體,不同於auto 變數,該變數的記憶體只被分配一次,因此其值在下次呼叫時仍維持上次的值;   (

C++類成員變數成員指標變數小結

指標的確有點難理解,不過它之所以存在並大範圍使用,這樣做是有一定道理的。 一、C++中的類和結構使用指標定義成員作用 1、多型的要求。 如果要使用同一介面,多型設計,那麼就一定要使用基類指標。只有指標才能在實力化後動態的判斷使用哪個方法。2、程式碼複用。有一些程式要設計

C++staticconst關鍵字的作用

修飾 程序 一次 sta 聲明 必須 bsp 進行 函數調用 static 1.static聲明的變量內存只被分配一次。auto變量(局部變量)在棧內存區堆放,static變量存放於數據區,程序結束才會釋放。 2.模塊內聲明的static全局變量,可以被該模塊所有函數訪

c++成員函數指針數組定義和初始化方法

fun all turn bsp ati const 成員函數指針 溢出 cat 實際項目中經常遇到很多類似操作,比如命令碼對應執行函數等,對於此類操作,比較好的方式是使用const數組,將命令碼和操作函數綁定在一起,通過查表方式找到操作函數,並執行操作函數。這樣可以簡化代

php類的$this,staticconst,self這幾個關鍵字使用方法

ons all 丟失 static ret 方法名 style sin 靜態方法 本篇文章主要分享一下關於php類中的$this,static,final,const,self這幾個關鍵字使用方法 $this $this表示當前實例,在類的內部方法訪問未聲明為const及s

C++的常量(一) const限定符

無法 簡單的 對象 可能 函數重載 struct 理解 變量 必須 最近在重新看<<C++ Primer>>,第一遍的時候const和constexpr看得並不太懂,這次又有了些更新的理解,當然可能仍然有許多不對的地方... 首先,const限定符即

Java成員變數、區域性變數、全域性變數、靜態變數存在位置及初始化

根據定義變數位置的不同,可以將變數分為成員變數和區域性變數。 成員變數是 定義在一個類的變數:類中方法外 區域性變數是定義在一個方法內的變數:方法中 成員變數分為: 靜態屬性:隨類的存在而存在,是在類載入的初始化 非靜態屬性:隨例項的屬性存在而存在。 區域性變數: 區域性變數不能加s

java成員變數和區域性變數

1.成員變數   在類中定義,用來描述物件將要有什麼。 2.區域性變數 在類的方法中定義,在方法中臨時儲存資料 成員變數和區域性變數區別 1.作用域不同 成員變數的作用域在整個類內部都是可見的 區域性變數的作用僅限於定義它的方法、 2.初始值不同 jav

c++普通變數,引用變數 ,指標變數用例項讓你親自體會

int a1 = 10; int a2 = 20; int a3 = a1;//賦值語句,可以理解成資料的克隆,a3與a1 不在是指向一個物件 int &b = a1; //int &b2 = 900; //不合法,非常量引用的初始值必須左值 int *c =

C, C++全域性變數的預設值

來源:http://blog.csdn.net/yanzheshi/article/details/45950275 在GCC編譯器下各個型別的全域性變數的預設值:  1、表示數字的變數型別預設值都為0  2、bool型預設值為false  3、stri

C#靜態變數 、靜態方法的說明

1.靜態變數在C#程式中,沒有全域性變數的概念,這意味著所有的成員變數只有該類的例項才能操作這些資料,這起到了“資訊隱藏”的作用。但有些時候,這樣做卻不是個明智的選擇。假設我們要定義一個圖書類,要求該類能儲存圖書的數量,即每增加一本圖書(定義一個例項),圖書的數量應該加1。如果沒有靜態變數,我們需要將圖書的數

C#靜態變數和 靜態方法

C#中靜態變數和 靜態方法 static節省了構造物件時造成的效能損耗,其次還能用於一些特殊環境(如惡漢式單例) 但是由於靜態成員在程式載入之前就進入記憶體,直到程式結束才會銷燬,所以 在程式中如果大量使用static來宣告型別或成員,也會造成系統資源的浪費。 一般靜態的就代表全域性。表示任何類