1. 程式人生 > >C++基礎--static靜態成員

C++基礎--static靜態成員

1. 靜態區域性物件

靜態區域性物件是位於函式內的靜態變數,在呼叫函式前就被建立並賦初值,在程式結束前都不會被撤銷,在函式多次呼叫過程中持續存在並保持它的值。
在標頭檔案中定義靜態變數不可行。因為如果在使用該標頭檔案的每個C語言檔案中定義靜態變數,則每個標頭檔案中都會存在一個單獨的靜態變數,會引起空間浪費或程式錯誤。不推薦在標頭檔案中定義任何變數。

2. 靜態類成員

static成員與類關聯,獨立於類的任意物件,類的全體物件共享static成員。static成員遵循正常公有/私有訪問規則。如果基類定義了static成員。如果不是private,既可以通過基類訪問該成員,也可以通過派生類訪問;如果是private,派生類不能訪問。
例如,銀行賬戶類,每個使用者具有餘額和擁有者,但每個賬戶利率相同。利率可以作為靜態類成員,計算利率的函式為靜態成員函式。或者,統計已建立的特定類型別物件的數量。

2.1 宣告和定義

宣告:在成員宣告前加上關鍵字static,關鍵字只出現在宣告處。
定義:類外定義使用作用域操作符將類和成員關聯。一般類的成員不能在類的定義體中初始化。但只要初始化式為常量表達式,整型const static資料成員就可在類的定義體中初始化,但仍必須在類外再定義,只是不必再指定初始值。

2.2 static資料成員

static資料成員必須在類定義體外部定義且只定義一次,無需重複指定static保留字。不能通過建構函式初始化,應該在定義時初始化。一旦成員名出現,成員定義就在類的作用域中,可直接使用static成員函式初始化。
static資料成員的型別可以是該成員所屬的類型別,非static成員被限定為自身類物件的指標或引用。
static資料成員可用作預設實參,非static成員不能用作預設實參,因為它的值不能獨立於所屬物件而使用。

2.3 static成員函式

static成員函式不是任何物件的組成部分,所以它沒有this指標,不能被宣告為const(因為將成員函式宣告為const表示不會修改該函式所在物件),也不能被宣告為虛擬函式。可以直接訪問所屬類的static成員,但不能直接使用非static成員。
使用

  • 通過作用域操作符”::”直接呼叫static成員
  • 通過物件、引用、指標間接呼叫

類的static成員的優點

  • 成員名在類的作用域中,避免與其他類成員或全域性物件名字衝突
  • 可以實施封裝。static成員可以是私有成員,全域性物件不可以,全域性物件會破壞封裝
  • 與特定類關聯。清晰顯示程式設計師意圖

3. 全域性變數 VS 靜態變數

a) 相同:都保留在靜態儲存區,生命週期都為整個程式
b) 全域性變數作用域為整個程式,在一個原始檔中定義,可作用於所有原始檔,不包含全域性變數的原始檔使用extern關鍵字再次宣告。若區域性重新定義,作用域除了這個區域性。
靜態區域性變數只對定義自己的函式體可見,靜態全域性變數作用於定義它的檔案。

#include <iostream>
#include <string>

using namespace std;

class Account {
public:
    void applyint(){
        amount += amount * interestRate;
    }
    //靜態成員函式
    static double rate(){ //返回利息
        return interestRate;
    }
    static void rate(double); //設定新利息
private:
    string owner;
    double amount;
    //只要初始化式為常量表達式,整型const static資料成員就可在類的定義體中初始化
    static const int period = 30;
    double daily_tbl[period];
    static double interestRate;
    static double initRate();
};
//Account的每個物件有兩個資料成員,沒有與static資料成員對應的資料成員,全體物件共享interestRate。

//static資料成員必須在類定義體外部定義且只定義一次。一旦成員名出現,成員定義就在類的作用域中,可直接使用static成員函式初始化
double Account::initRate() {
    interestRate = 3.0;
}
double Account::interestRate = initRate();
//const int Account::period;
//類外部定義靜態成員函式時,無需重複static保留字
void Account::rate(double newRate){
    interestRate = newRate;
}

int main(){
    Account ac1;
    Account *ac2 = &ac1;
    double rate;

    //正常呼叫靜態成員函式
    rate = ac1.rate();
    rate = ac2->rate();
    //使用作用域操作符用類直接呼叫靜態成員函式
    Account::rate();
    return 0;
}