我們可以使用static關鍵字把類成員定義為靜態的。當我們聲明類的成員為靜態時,這意味著無論創建多少個類的對象,靜態成員都只有一個副本。
靜態成員在類的所有對象都是貢獻的。如果不存在其他的初始化語句,在創建第一個對象時,所有的靜態數據都會被初始化為0。我們不能把靜態成員的初始化放置在類的定義中,但是可以在類的外部通過使用范圍解析運算符 :: 來重新聲明靜態變量從而對它進行初始化。
?
靜態成員變量
/*** static.cpp ***/ #include<iostream> using namespace std;class Box {public:static int objectCount;Box(double l = 2.0,double b = 2.0,double h = 2.0){cout << "Construct called." << endl;length = l;breadth = b;height = h;objectCount++;}double Volume(){return length*breadth*height;}private:double length;double breadth;double height; };int Box::objectCount = 0;int main() {Box box1(3.3,1.2,1.5);Box box2(8.5,6.0,2.0);cout << "Total object: " << Box::objectCount << endl; return 0;}
運行結果:
exbot@ubuntu:~/wangqinghe/C++/20190807$ g++ static.cpp -o static
exbot@ubuntu:~/wangqinghe/C++/20190807$ ./static
Construct called.
Construct called.
Total object: 2
靜態成員函數:
如果把函數成員聲明為靜態的,就可以把函數和類的任何特定對象獨立開來。靜態成員函數即使在類對象不存在的情況下也可以被調用,靜態函數只要使用類名加范圍解析運算符::就可以訪問。
靜態成員函數只能訪問靜態成員數據、其他靜態成員函數和類外部的其他函數。
靜態成員函數有一個類范圍,他們不能訪問類的this指針。也可以使用靜態成員函數來判斷類的某些對象是否被創建。
?
靜態成員函數和普通成員函數的區別:
靜態成員函數沒有this指針,只能訪問靜態成員(包括靜態成員變量和靜態成員函數)
普通成員函數有this指針,可以訪問類中的任意成員;而靜態成員函數沒有this指針。
?
/*** staticfun.cpp ***/ #include<iostream> using namespace std;class Box {public:static int objectCount;Box(double l = 2.0,double b = 2.0,double h = 2.0){cout << "Construct called." << endl;length = l;breadth = b;height = h;objectCount++;}double Volume(){return length*breadth*height;}static int getCount(){return objectCount;}private:double length;double breadth;double height; };int Box::objectCount = 0;int main() {cout << "Init stage count: " << Box::getCount() << endl;Box box1(3.3,1.2,1.5);Box box2(8.5,6.0,2.0);cout << "final stage count: " << Box::getCount() << endl; return 0; }
運行結果:
exbot@ubuntu:~/wangqinghe/C++/20190807$ g++ staticfun.cpp -o staticfun
exbot@ubuntu:~/wangqinghe/C++/20190807$ ./staticfun
Init stage count: 0
Construct called.
Construct called.
final stage count: 2
?
靜態成員變量在類中僅僅是聲明,沒有定義,所以要在類的外面
定義,實際上是給靜態成員變量分配內存,如果不加定義就會報錯,初始化是賦一個初始值,而定義是分配內存。
?
利用靜態成員變量來了解構造和析構函數的調用情況。
#include<iostream> using namespace std;class Cpoint {public:static int value;static int num;Cpoint(int x,int y){xp = x;yp = y;value++;cout << "call construct " << value << endl;}~Cpoint(){num++;cout << "call deconstruct " << num << endl;}private:int xp;int yp; };int Cpoint::value = 0; int Cpoint::num = 0;class CRect {public:CRect(int x1,int x2):mpt1(x1,x2),mpt2(x1,x2){ cout << "call construct" << endl; }~CRect(){cout << "call deconstruct" << endl;}private:Cpoint mpt1,mpt2; };int main() {CRect p(10,20);cout << "hello world!" << endl;return 0; }
運行結果:
exbot@ubuntu:~/wangqinghe/C++/20190807$ g++ construct.cpp -o construct -g
exbot@ubuntu:~/wangqinghe/C++/20190807$ ./construct
call construct 1
call construct 2
call construct
hello world!
call deconstruct
call deconstruct 1
call deconstruct 2
?
類中特殊成員變量的初始化問題:
- 常量變量:必須通過構造函數參數列表進行初始化
- 引用變量:必須通過構造函數參數列表進行初始化
- 普通靜態變量:要在類外通過“::”初始化
- 靜態整型變量:可以直接在定義的時候初始化
- 靜態非整型常量:不能直接在定義的時候初始化。要在類通過”::”初始化