在 C++ 中使用 static 关键字

Jinku Hu 2023年10月12日
  1. 在 C++ 中使用 static 关键字声明具有静态持续时间的变量
  2. 使用 static 关键字在 C++ 中声明类的静态成员
在 C++ 中使用 static 关键字

本指南将解释如何在 C++ 中使用 static 关键字的几种方法。

在 C++ 中使用 static 关键字声明具有静态持续时间的变量

static 关键字可用于声明具有静态持续时间的局部变量。与命名可能暗示的相反,具有静态持续时间的局部变量意味着即使在声明变量的块超出范围之后,它的值仍然在内存中保持活动状态。

基本上,这些局部变量可以在定义它们的函数调用之间保存它们的值。请注意,incrementCount 函数有一个名为 count 的变量,它的初始化值为 0count 属性分配在活动的内存区域中,直到程序终止。因此,每次调用 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
作者: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

DelftStack.com 创始人。Jinku 在机器人和汽车行业工作了8多年。他在自动测试、远程测试及从耐久性测试中创建报告时磨练了自己的编程技能。他拥有电气/电子工程背景,但他也扩展了自己的兴趣到嵌入式电子、嵌入式编程以及前端和后端编程。

LinkedIn Facebook

相关文章 - C++ Static