對於每一個基於相同類別所產生的物件而言,它們會擁有各自的資料成員,然而在某些時候,您會想要這些物件擁有相同的資料成員,舉個例子來說,在Ball類
別中,您打算使用到圓周率PI這個資料,因為對於任一個Ball的實例而言,圓周率都是相同的,您不需要讓不同的Ball實例擁有各自的圓周率資料成員。
您可以將PI資料成員宣告為"static",被宣告為"static"的資料成員,又稱「靜態資料成員」,靜態成員是屬於類別所擁有,而不是個別的物
件,您可以將靜態成員視為每個物件實例所共享的資料成員。要宣告靜態資料成員,只要在宣告資料成員時加上"static"關鍵字就可以了,例如:
#include <string> using namespace std;
class Ball { public: // 宣告靜態成員 static double PI; // const 靜態成員可以在類別定義中初始化 // static const double PI = 3.14159;
Ball(); Ball(double, const char*); Ball(double, string&); double radius() { return _radius; } string& name() { return _name; } void radius(double radius) { _radius = radius; } void name(const char *name) { _name = name; } void name(string& name) { _name = name; } double volumn() { return (4 / 3 * PI * _radius * _radius * _radius); } private: double _radius; // 半徑 string _name; // 名稱 };
#include <string> #include "Ball.h" using namespace std;
// 非const靜態成員要在類別定義外初始化 double Ball::PI = 3.14159;
// 預設建構函式 Ball::Ball() { _radius = 0.0; _name = "noname ball"; }
Ball::Ball(double radius, const char *name) { _radius = radius; _name = name; }
Ball::Ball(double radius, string &name) { _radius = radius; _name = name; }
非const的static成員要在類別定義區塊之外初始化,靜態成員屬
於類別所擁有,可以在
不使用名稱參考下,直接使用類別名稱加上::運算子來存取靜態資料成員,不過靜態資料成員同樣遵守"public"、"protected"與"private"的存取限制,所以若
您要直接存取靜態資料成員,必須注意它的權限,例如必須設定為"public"成員的話就可以如下存取:
#include <iostream> #include "Ball.h" using namespace std;
int main() { cout << Ball::PI << endl;
return 0; }
執行結果:
雖然您也可以在宣告物件之後,透過物件名稱加上'.'運算子來存取靜態資料成員,但是這個方式並不被鼓勵,通常建議使用類別名稱加上'.'運算子來存取,
一方面也可以避免與非靜態資料成員混淆,例如下面的方式是不被鼓勵的:
Ball
ball;
cout
<<
ball.PI << endl;
與靜態資料成員類似的,您也可以宣告函式成員為"static"方法,又稱「靜態函式」,被宣告為靜態的函式通常是作為工具函式,例如在Ball類別上增
加一個角度轉徑度的函式toRadian():
#include <string> using namespace std;
class Ball { public: // 宣告靜態資料成員 static double PI; Ball(); Ball(double, const char*); Ball(double, string&); // 宣告靜態函式 static double toRadian(double); double radius() { return _radius; } string& name() { return _name; } void radius(double radius) { _radius = radius; } void name(const char *name) { _name = name; } void name(string& name) { _name = name; } double volumn() { return (4 / 3 * PI * _radius * _radius * _radius); } private: double _radius; // 半徑 string _name; // 名稱 };
#include <string> #include "Ball.h" using namespace std;
// 初始靜態資料成員 double Ball::PI = 3.14159;
// 實作靜態函式 double Ball::toRadian(double angle) { return 3.14159 / 180 * angle; }
// 預設建構函式 Ball::Ball() { _radius = 0.0; _name = "noname ball"; }
Ball::Ball(double radius, const char *name) { _radius = radius; _name = name; }
Ball::Ball(double radius, string &name) { _radius = radius; _name = name; }
與靜態資料成員一樣的,您可以透過類別名稱使用::運算子來存取"static"函式,當然要注意權限設定,例如設定為"public"的話可以如下存
取:
cout
<<
"角度90等於徑度"
<< Ball::toRadian(90)
<< endl;
由於靜態成員是屬於類別而不是物件,所以當您呼叫靜態函式時,並不會傳入物件的位址,所以靜態函式中不會有this指標,由於沒有this指標,所以在C
++的靜態函式中不允許使用非靜態成員,因為沒有this來儲存物件的位址,也就無法辨別要存取的是哪一個物件的成員,事實上,如果您在靜態函式中使用非
靜態資料成員,在編譯時就會出現以下的錯誤訊息:
invalid
use of member
`Ball::_radius' in static member function
或者是在靜態函式中呼叫非靜態函式,在編譯時就會出現以下的錯誤訊息:
cannot
call member
function `std::string& Ball::name()' without object
|