C++中的static的作用
C++中的關鍵字static,顧名思義表示靜止,靜態,下面是C++中static的一些常見應用
一,作用於函數內部的局部變量
局部作用域靜態變量的特點:當一個函數返回后,下一次再調用時,該變量還會保持上一回的值,函數內部的靜態變量只開辟一次空間,且不會因為多次調用產生副本,也不會因為函數返回而失效
例如:
如果我想實現fun()函數功能:在函數內部定義count計數器,打印出每次調用它的次數,你可能會這樣寫,如下
#include<iostream>
using namespace std;
void fun()
{
int count = 0;//不加關鍵字static
count++;
cout << "count=" << count << endl;
}
int main()
{
cout << "Calling the “fun()”for the first time! " << endl;
fun();
cout << "Calling the “fun()”for the second time! " << endl;
fun();
return 0;
}
我們預計結果為:
第一次調用,打印出結果 1
第二次調用,打印出結果 2
我們試着運行后,結果並不是我們想要的,如下圖:
兩次運行結果都是1,這是為什么呢,原來是每次調用函數結束后,count值會失效,當再次調用函數時,count值會重新生成,初始值為1,這就達不到我們想要的結果,那該怎么辦呢?這時候就需要static關鍵字作用的靜態變量,如下:
#include<iostream>
using namespace std;
void fun()
{
static int count = 0;//static 作用的靜態變量
count++;
cout << "count=" << count << endl;
}
int main()
{
cout << "calling the “fun()”for the first time! " << endl;
fun();
cout << "calling the “fun()”for the second time! " << endl;
fun();
return 0;
}
運行結果跟我們想要的結果就一致啦
另外,普通局部變量如果未賦予初值,編譯器會報錯
報錯如下:
當局部變量加上static 后,定義時未賦予初值時,會默認初始化0
二,作用於類的成員,解決同一個類的不同對象之間數據和函數共享問題
1,作用於類的數據成員,使其成為靜態數據成員
靜態成員在每一個類中只有一個副本,由該類所有對象共同維護和使用,從而實現同一個類的不同對象數據共享。需要注意的是,如下
訪問靜態數據成員方式:類名::標識符
對靜態數據成員初始化:在類定義外進行
之所以進行類名::標識符進行訪問,是因為靜態數據成語哪不屬於任何一個對象,而在類外進行定義是因為需要以這種方式專門為他們分配空間。
舉例說明:
直接在類內定義靜態數據成員,編譯器會報錯
錯誤如下:
正確做法:
下面通過一段代碼,理解一下對於“同一個類的不同對象數據共享”的理解,代碼如下:
#include <iostream>
using namespace std;
class Point { //Point類定義
public: //外部接口
Point(int x = 0, int y = 0) : x(x), y(y) { //構造函數
//在構造函數中對count累加,所有對象共同維護同一個count
count++;
}
Point(Point &p) { //拷貝構造函數
x = p.x;
y = p.y;
count++;
}
Point() { count--; }
int getX() { return x; }
int getY() { return y; }
void showCount() { //輸出靜態數據成員
cout << " Object count = " << count << endl;
}
private: //私有數據成員
int x, y;
static int count; //靜態數據成員聲明,用於記錄點的個數
};
int Point::count = 0; //靜態數據成員定義和初始化,使用類名限定
int main() { //主函數
Point a(4, 5); //定義對象a,其構造函數回使count增1
cout << "Point A: " << a.getX() << ", " << a.getY();
a.showCount(); //輸出對象個數
Point b(a); //定義對象b,其構造函數回使count增1
cout << "Point B: " << b.getX() << ", " << b.getY();
b.showCount(); //輸出對象個數
cout << "Point A: " << a.getX() << ", " << a.getY();
a.showCount(); //輸出對象個數
return 0;
}
輸出結果:
這里的Point類里面的A,B對象共有的屬性object count 都是2 。該運行結果清晰的顯示了同一個類的不同對象數據共享的理解。
2,作用於類的函數成員,使其成為靜態函數成員
靜態成員函數就是使用static關鍵字聲明的函數成員,同靜態數據成員一樣,靜態成員函數也屬於整個類,由該類所有對象共同擁有,為所有對象共享
(1)靜態成員函數主要用於處理該類的靜態數據成員,可以直接調用靜態數據成員。如果訪問非靜態成員,要通過對象來訪問。例子如下:**
**
class A {
public:
static void f(A a);
private:
int x;
static int y;
};
void A::f(A a)
{
cout << x;//對x的引用是錯誤的
cout << a.x;//正確
cout << y;//對x的引用是正確的的,引用靜態數據成員
}
上面代碼中報錯如下:
所以,靜態成員函數訪問非靜態成員,一定要通過對象來訪問
(2)如果想在類外調用靜態成員函數呢?------類外代碼一般使用類名和作用域操作符來調用靜態成員函數。
訪問方式:一般通過類名::函數名調用,也可用類.函數名調用
舉例說明,如下:
三,總結:
當static作用於非類內函數的局部變量時,每次函數調用不會隨着函數返回而失效,當static作用於類內成員時,由該類所有對象共同維護和使用,從而實現同一個類的不同對象數據共享。