對於每一個基於相同類別所產生的物件而言,它們會擁有各自的資料成員,然而在某些時候,您會想要這些物件擁有相同的資料成員,舉個例子來說,在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:
I = 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:
I
<< 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:
I = 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