static 关键字可以修饰变量和函数,在 Java 中还可以修饰内部类,C++ 中是不能这么做的。

# 前言

static 的作用和 extern 关键字有些关联,可以先看下 (C++ extern 关键字)[]。

# 修饰全局变量

如果全局变量被 static,那么该变量的作用域只能在当前文件中,即便使用 extern 也无法被其他文件访问。static 修饰的变量在程序启动时被初始化,生命周期和程序一样长。
对于 extern 文章中的代码,把 test1.cpp 中的 const 变成 static,编译时就会报错。

test1.cpp
static int a = 1;
static int b = 2;
test.cpp
#include <iostream>
using namespace std;
// extern int a; error: edeclaration of 'a' with a different type: 'int' vs 'const int'
extern const int a;
// extern const int b = 2; error: Redefinition of 'b'
int main() {
  cout << a << endl; // 1
  // extern const int a = 3; error: 'extern' variable cannot have an initializer
  int a = 3;
  cout << a << endl; // 3
  extern const int b;
  cout << b << endl; // 2
  // const int b = 4; error: Non-extern declaration of 'b' follows extern declaration
  // b = 4; error: Cannot assign to variable 'b' with const-qualified type 'const int'
}
Undefined symbols for architecture arm64:
  "_a", referenced from:
      _main in test-7b769d.o
  "_b", referenced from:
      _main in test-7b769d.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# 修饰局部变量

局部变量如果被 static 修饰,在函数结束之后不会被销毁,会在下次进入函数时复用。它的作用域仅限于当前函数中。

#include <iostream>
using namespace std;
void func() {
  static int a = 0;
  a++;
  cout << a << endl;
}
int main() {
  func(); // 1
  func(); // 2
  // cout << a << endl; error: Use of undeclared identifier 'a'
}

# 修饰函数

修饰函数的效果和修饰全局变量的效果是一样的,将函数的作用域限制在了当前文件中。

test1.cpp
#include <iostream>
using namespace std;
void func1() {
  cout << "func1" << endl;
}
static void func2() {
  cout << "func2" << endl; 
}
test.cpp
#include <iostream>
using namespace std;
extern void func1();
extern void func2();
int main() {
  func1(); // fun1
  
  // func2(); symbol(s) not found for architecture arm64
}

# 修饰类成员变量和函数

静态变量不能在类内定义,必须在全局作用域定义

#include <iostream>
using namespace std;
class A {
public:
  static int a;
  // static int b = 1; error: Non-const static data member must be initialized out of line
  int c;
  
  static void func1() {
    cout << "func1" << endl;
  }
  void func2() {
    cout << "func2" << endl;
  }
};
int A::a = 1;
int main() {
  cout << A::a << endl; // 1
  // int d = A::c error: Invalid use of non-static data member 'a'
  A::func1(); // func1
  A aa;
  aa.c = 2;
  cout << aa.c << endl; // 2
  aa.func2(); // func2
  // A::func2(); error: Call to non-static member function without an object argument
}