一、static 成員變量
對於特定類型的全體對象而言,有時候可能需要訪問一個全局的變量。比如說統計某種類型對象已創建的數量。
如果我們用全局變量會破壞數據的封裝,一般的用戶代碼都可以修改這個全局變量,這時可以用類的靜態成員來解決這個問題。
非static數據成員存在於類類型的每個對象中,static數據成員獨立該類的任意對象存在,它是與類關聯的對象,不與類對象關聯。
(1)、static成員的定義
static成員需要在類定義體外進行初始化與定義
(2)、特殊的整型static const成員
整型static const成員可以在類定義體中初始化,該成員可以不在類體外進行定義
C++ Code
1
2
3
4
5
6
7
8
9
10
11
12
13
class Test
{
public:
Test(): a(0) {}
enum {size1 = 100, size2 = 200};
private:
const int a; //只能在構造函數初始化列表中初始化
static int b; //在類的實現文件中定義並初始化
const static int c; //與 static const int c; 相同。
};
int Test::b = 0; //static成員變量不能在構造函數初始化列表中初始化,因為它不屬於某個對象。
const int Test::c = 0; //注意:給靜態成員變量賦值時,不需要加static修飾符,但要加const
(3)、static成員優點:
static成員的名字是在類的作用域中,因此可以避免與其它類成員或全局對象名字沖突。
可以實施封裝,static成員可以是私有的,而全局對象不可以
閱讀程序容易看出static成員與某個類相關聯,這種可見性可以清晰地反映程序員的意圖。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#ifndef _COUNTED_OBJECT_H_ #define _COUNTED_OBJECT_H_ class CountedObject { public: CountedObject(); ~CountedObject(); public: static int GetCount(); private: static int count_; // 靜態成員的引用性聲明 }; #endif // _COUNTED_OBJECT_H_ |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include "CountedObject.h" int CountedObject::count_ = 0; // 靜態成員的定義性聲明 CountedObject::CountedObject() { ++count_; } CountedObject::~CountedObject() { --count_; } int CountedObject::GetCount() { return count_; } |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include "CountedObject.h" #include <iostream> using namespace std; int main(void) { //cout<<CountedObject::count_<<endl; cout << CountedObject::GetCount() << endl; CountedObject co1; //cout<<CountedObject::count_<<endl; cout << CountedObject::GetCount() << endl; CountedObject *co2 = new CountedObject; //cout<<CountedObject::count_<<endl; cout << CountedObject::GetCount() << endl; delete co2; //cout<<CountedObject::count_<<endl; cout << CountedObject::GetCount() << endl; } |
上述程序定義一個靜態成員變量和靜態成員函數,可以通過類名:: 訪問static 成員變量,也可以通過非/靜態成員函數訪問。
二、static 成員函數
static成員函數沒有隱含的this指針
非靜態成員函數可以訪問靜態成員
靜態成員函數不可以訪問非靜態成員(實際上是直接訪問是不可以的,間接地訪問是可以的,比如通過類指針或類引用)
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#include <iostream> using namespace std; class Test { public: Test(int y) : y_(y) { } ~Test() { } void TestFun() { cout << "x=" << x_ << endl; //OK,非靜態成員函數可以訪問靜態成員 TestStaticFun(); } static void TestStaticFun() { cout << "TestStaticFun ..." << endl; //TestFun(); Error,靜態成員函數不能調用非靜態成員函數 //cout<<"y="<<y_<<endl; Error,靜態成員函數不能訪問非靜態成員 } static int x_; // 靜態成員的引用性說明 int y_; }; int Test::x_ = 100; // 靜態成員的定義性說明 int main(void) { cout << sizeof(Test) << endl; return 0; } |
三、類/對象大小計算
類大小計算遵循前面學過的結構體對齊原則(參照這里)
類的大小與數據成員有關與成員函數無關(空類大小為1個字節)
類的大小與靜態數據成員無關
虛函數對類的大小的影響(參考這里)
虛繼承對類的大小的影響(參考這里)
參考:
C++ primer 第四版
Effective C++ 3rd
C++編程規范