在 C++ 中使用 static 關鍵字
本指南將解釋如何在 C++ 中使用 static
關鍵字的幾種方法。
在 C++ 中使用 static
關鍵字宣告具有靜態持續時間的變數
static
關鍵字可用於宣告具有靜態持續時間的區域性變數。與命名可能暗示的相反,具有靜態持續時間的區域性變數意味著即使在宣告變數的塊超出範圍之後,它的值仍然在記憶體中保持活動狀態。
基本上,這些區域性變數可以在定義它們的函式呼叫之間儲存它們的值。請注意,incrementCount
函式有一個名為 count
的變數,它的初始化值為 0
。count
屬性分配在活動的記憶體區域中,直到程式終止。因此,每次呼叫 incrementCount
都會向給定的整數新增一個單位。
#include <iostream>
using std::cout;
using std::endl;
int incrementCount() {
static int count = 0;
return ++count;
}
int main() {
for (int i = 0; i < 20; ++i) {
if (i % 2 == 0) incrementCount();
}
cout << incrementCount() - 1 << endl;
return EXIT_SUCCESS;
}
輸出:
10
使用 static
關鍵字在 C++ 中宣告類的靜態成員
另一方面,static
關鍵字用於宣告類的靜態資料成員。這些成員與類型別本身相關聯,而不是與類的特定例項相關聯。因此,如果我們為給定類定義靜態資料成員,則該類型別的每個例項都將具有相同的資料成員值。與擁有私有成員不同,前者在記憶體中只有一個副本。從類記憶體佔用的角度來看,後一個特性使靜態資料成員高效。
static
資料成員的定義和初始化與常規資料成員不同。static
成員應該在類內宣告並在相關原始檔中的類外定義。static
關鍵字僅用於類內的宣告。任何 static
資料成員都不能由建構函式初始化,並且它們不能在類體內初始化,除非它們具有 const
整數型別。後一種型別仍然需要在沒有初始值規範的情況下在類主體之外定義。下面的示例演示了 static
資料成員 name
的簡單用法,它使用字串文字進行初始化,然後使用 setNewName
函式進行修改。
#include <iostream>
#include <string>
#include <utility>
using std::cin;
using std::cout;
using std::endl;
using std::string;
class MyClass1 {
private:
static string name;
string nickname;
public:
explicit MyClass1(string n) : nickname(std::move(n)){};
static string getName() { return name; }
static void setNewName(std::basic_string<char> s) { name = std::move(s); }
string getNickname() { return nickname; }
~MyClass1() = default;
};
string MyClass1::name = "Static name";
int main() {
MyClass1 m1(string("April"));
MyClass1 m2(string("Maude"));
cout << MyClass1::getName() << endl;
MyClass1::setNewName("New name");
cout << MyClass1::getName() << endl;
return EXIT_SUCCESS;
}
輸出:
Static name
New name
或者,該類可能具有未繫結到任何物件的 static
函式成員,因此它們不能在其主體中引用 this
物件。通常,這些函式不需要像 static
資料成員那樣有單獨的宣告和定義,如下面的示例程式所示。儘管如此,大多數現代風格指南通常會要求程式設計師將兩者解耦。
#include <iostream>
#include <string>
#include <utility>
using std::cin;
using std::cout;
using std::endl;
using std::string;
class MyClass1 {
private:
static string name;
string nickname;
public:
explicit MyClass1(string n) : nickname(std::move(n)){};
static string getName() { return name; }
static void setNewName(std::basic_string<char> s) { name = std::move(s); }
string getNickname() { return nickname; }
static bool compareStrings(const std::basic_string<char>& s1,
const std::basic_string<char>& s2) {
if (s1 == s2)
return true;
else
return false;
}
~MyClass1() = default;
};
string MyClass1::name = "Static name";
int main() {
MyClass1 m1(string("April"));
MyClass1 m2(string("Maude"));
MyClass1::compareStrings(m1.getNickname(), m2.getNickname())
? cout << "strings are equal" << endl
: cout << "strings are not equal" << endl;
MyClass1::compareStrings(MyClass1::getName(), MyClass1::getName())
? cout << "strings are equal" << endl
: cout << "strings are not equal" << endl;
return EXIT_SUCCESS;
}
輸出:
strings are not equal
strings are equal