C++ 程式設計
static 關鍵字可以在四種不同的方式中使用
static 關鍵字也可以用於函式、函式內部、類、類成員(資料和函式)、結構體、聯合體(但不能用於聯合體的成員)中,我們將分別介紹每種用法。
使用static修飾符使變數具有靜態生命週期,而對於全域性變數,則使它們需要內部連結(變數將無法從同一專案中位於其他檔案中的程式碼訪問)。
- 靜態生命週期
- 意味著靜態變數需要在檔案範圍內進行初始化,並且在執行時,將一直存在並保持更改,直到程式程序關閉,靜態變數的特定銷燬順序是未定義的。
static 變數例項共享相同的記憶體位置。這意味著它們在函式呼叫之間保留其值。例如,在以下程式碼中,函式內部的靜態變數用於跟蹤該函式被呼叫的次數
void foo() {
static int counter = 0;
cout << "foo has been called " << ++counter << " times\n";
}
int main() {
for( int i = 0; i < 10; ++i ) foo();
}
- 內部連結
當用於自由函式、全域性變數或全域性常量時,它指定內部連結(與 extern 相反,後者指定外部連結)。內部連結將對資料或函式的訪問限制為當前檔案。
在任何函式或類之外使用的示例
static int apples = 15;
- 定義一個名為apples的“靜態全域性”變數,初始值為 15,僅從該翻譯單元可見。
static int bananas;
- 定義一個名為bananas,初始值為 0,僅從該翻譯單元可見。
int g_fruit;
- 定義一個名為g_fruit的全域性變數,初始值為 0,從每個翻譯單元可見。這種變數通常被認為是糟糕的風格。
static const int muffins_per_pan=12;
- 定義是一個名為muffins_per_pan的變數,僅在此翻譯單元中可見。static 關鍵字在此處是多餘的。
const int hours_per_day=24;
- 定義一個名為hours_per_day的變數,僅在此翻譯單元中可見。(這與).
static const int hours_per_day=24;
static void f();
- 宣告存在一個名為f的函式,它不接受引數且沒有返回值,定義在該翻譯單元中。這種前向宣告通常在定義相互遞迴函式時使用。
static void f(){;}
- 定義函式f()在上面宣告。此函式只能從該翻譯單元中的其他函式和成員呼叫;它對其他翻譯單元不可見。
宣告為靜態的成員函式或變數在物件型別的所有例項之間共享。這意味著對於任何物件型別,成員函式或變數只有一份副本存在。
- 無需物件即可呼叫的成員函式
當用於類函式成員時,函式不將例項作為隱式 this 引數,而是表現得像自由函式。這意味著靜態類函式可以在不建立類例項的情況下呼叫
class Foo {
public:
Foo() {
++numFoos;
cout << "We have now created " << numFoos << " instances of the Foo class\n";
}
static int getNumFoos() {
return numFoos;
}
private:
static int numFoos;
};
int Foo::numFoos = 0; // allocate memory for numFoos, and initialize it
int main() {
Foo f1;
Foo f2;
Foo f3;
cout << "So far, we've made " << Foo::getNumFoos() << " instances of the Foo class\n";
}
命名建構函式是使用靜態成員函式的一個很好的例子。命名建構函式是用於建立類物件而無需(直接)使用其建構函式的函式的名稱。這可能用於以下情況
- 繞過建構函式只能在它們的簽名不同時才能過載的限制。
- 透過使建構函式私有來使類不可繼承。
- 透過使建構函式私有來防止堆疊分配
宣告一個使用私有建構函式建立物件並返回物件的靜態成員函式。(它也可以返回指標或引用,但這種複雜性似乎沒有用,並且將其變成了 工廠模式 而不是傳統的命名建構函式。)
這是一個用於儲存可以在任何溫度標度中指定的溫度的類的示例。
class Temperature
{
public:
static Temperature Fahrenheit (double f);
static Temperature Celsius (double c);
static Temperature Kelvin (double k);
private:
Temperature (double temp);
double _temp;
};
Temperature::Temperature (double temp):_temp (temp) {}
Temperature Temperature::Fahrenheit (double f)
{
return Temperature ((f + 459.67) / 1.8);
}
Temperature Temperature::Celsius (double c)
{
return Temperature (c + 273.15);
}
Temperature Temperature::Kelvin (double k)
{
return Temperature (k);
}
在資料成員中使用 static 說明符將導致該成員由所有擁有者類及其派生類的例項共享。要使用靜態資料成員,您必須將資料成員宣告為 static,並在類宣告之外、檔案範圍內對其進行初始化。
當用於類資料成員時,該類的所有例項共享該變數的一個副本。
class Foo {
public:
Foo() {
++iNumFoos;
cout << "We have now created " << iNumFoos << " instances of the Foo class\n";
}
private:
static int iNumFoos;
};
int Foo::iNumFoos = 0; // allocate memory for numFoos, and initialize it
int main() {
Foo f1;
Foo f2;
Foo f3;
}
在上面的示例中,靜態類變數 numFoos 在 Foo 類的三個例項(f1、f2 和 f3)之間共享,並記錄了 Foo 類被例項化的次數。
