在 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