1. 程式人生 > 程式設計 >一文讀懂c++之static關鍵字

一文讀懂c++之static關鍵字

一、靜態變數

與C語言一樣,可以使用static說明自動變數。根據定義的位置不同,分為靜態全域性變數和靜態區域性變數。

  • 全域性變數是指在所有花括號之外宣告的變數,其作用域範圍是全域性可見的,即在整個專案檔案內都有效。使用static修飾的全域性變數是靜態全域性變數,其作用域有所限制,僅在定義該變數的原始檔內有效,專案中的其他原始檔中不能使用它。
  • 塊內定義的變數是區域性變數,從定義之處開始到本塊結束處為止是區域性變數的作用域。使用static修飾的區域性變數是靜態區域性變數,即定義在塊中的靜態變數。靜態區域性變數具有區域性作用域,但卻具有全域性生存期。
  • 靜態區域性變數具有區域性作用域,但卻具有全域性生存期。也就是說,靜態區域性變數在程式的整個執行期間都存在,它佔據的空間一直到程式結束時才釋放,但僅在定義它的塊中有效,在塊外並不能訪問它。
  • 靜態變數均儲存在全域性資料區,靜態區域性變數只執行一次初始化。如果程式未顯式給出初始值,則相當於初始化為0;如果顯式給出初始值,則在該靜態變數所在塊第一次執行時完成初始化。
#include<iostream>
using namespace std;

//全域性靜態變數
static int glos_s=10;
//全域性變數
int glos_a=10;

void f(){
  int a=1; //區域性變數a
  static int fs=1; //靜態區域性變數fs,完成初始化。
  a+=2;
  fs+=2;
  glos_s+=10;
  glos_a+=10;
  cout<<"在f中:區域性變數a="<<a<<" 靜態區域性變數fs="<<fs<<" 全域性變數glos_a="<<glos_a<< " 全域性靜態變數glos_s=" << glos_s <<endl;
}
int main(){
   f(); //在f中:區域性變數a=3 靜態區域性變數fs=3 全域性變數glos_a=20 全域性靜態變數glos_s=20
   f(); //在f中:區域性變數a=3 靜態區域性變數fs=5 全域性變數glos_a=30 全域性靜態變數glos_s=30
  return 0; 
}

二、類中的static

1、定義類的靜態成員

類的靜態成員有兩種:靜態成員變數和靜態成員函式。在類體內定義類的成員時,
在前面新增static關鍵字後,該成員即成為靜態成員。

  • 類的靜態成員被類的所有物件共享,不論有多少物件存在,靜態成員都只有一份儲存在公用記憶體中。對於靜態成員變數,各物件看到的值是一樣的。
  • 定義類靜態成員變數時,在類定義中宣告靜態成員變數,然後必須在類體外定義靜態成員變數的初值。這個初值不能在類體內賦值。
  • 給靜態成員變數賦初值的格式如下:型別 類名::靜態成員變數=初值;
  • 注意,在類體外為靜態成員變數賦初值時,前面不能加static關鍵字,以免和一般的靜態變數相混淆。在類體外定義成員函式時,前面也不能加static關鍵字。

2、類靜態成員的使用

訪問靜態成員時,成員前面既可以用類名作字首,也可以使用物件名或物件指標作字首。這與訪問類成員時僅能使用物件名或物件指標作字首是不同的。訪問類靜態成員的一般格式如下:

  • 類名::靜態成員名
  • 物件名.靜態成員名
  • 物件指標->靜態成員名

類的靜態成員函式沒有this指標,不能在靜態成員函式內訪問非靜態的成員,即通常情況下,類的靜態成員函式只能處理類的靜態成員變數。靜態成員函式內也不能呼叫非靜態成員函式。

#include<iostream>

using namespace std;

class Student{
  public:
    int id;
    string name;
    static int money;
    static void printlnMoney(Student &stu);  
};
//靜態成員必須在類體外初始化,並且不能在類體內賦值
int Student::money=10000;
//靜態成員函式的實現
void Student::printlnMoney(Student &stu){
  cout << "name:" << stu.name <<" money:" << stu.money << endl;
}

int main(){
  Student stu;
  stu.id=1;
  stu.name="小米";
  //使用物件呼叫靜態成員
  stu.printlnMoney(stu);//name:小米 money:10000
  Student *stu2=new Student();
  stu2->id=1;
  stu2->name="美團";
  //使用指標呼叫靜態成員
  stu2->printlnMoney(*stu2);//name:美團 money:10000
  //使用類名呼叫靜態成員
  Student::money=50000;
  Student::printlnMoney(*stu2);//name:美團 money:50000
  Student::printlnMoney(stu);//name:小米 money:50000
  return 0; 
}

3、普通成員與靜態成員

對於普通成員變數,每個物件有各自的一份,而靜態成員變數只有一份,被同類所有物件共享。普通成員函式一定是作用在某個物件上的,而靜態成員函式並不具體作用在某個物件上。

訪問普通成員時,要通過“物件名.成員名”等方式,指明要訪問的成員變數是屬於哪個物件的,或要呼叫的成員函式作用於哪個物件;

訪問靜態成員時,則可以通過“類名::成員名”的方式訪問,不需要指明被訪問的成員屬於哪個物件或作用於哪個物件。
因此,甚至可以在還沒有任何物件生成時就訪問一個類的靜態成員。非靜態成員的訪問方式其實也適用於靜態成員,也就是可以通過“物件名.成員名”的方式訪問,效果和“類名::成員名”這種訪問方式沒有區別

在通常情況下,除一種情況外,類的成員函式之間是允許互相呼叫的。具體來說,靜態函式與靜態函式之間、非靜態函式與非靜態函式之間是可以相互呼叫的,非靜態成員函式內可以呼叫靜態成員函式,但靜態成員函式內不能呼叫非靜態成員函式

以上就是一文讀懂c++之static關鍵字的詳細內容,更多關於c++ static關鍵字的資料請關注我們其它相關文章!