capl--static

一、static 总览

使用位置 核心作用 关键行为
类的静态成员变量 类级共享数据 所有对象共享一份,类外必须定义
类的静态成员函数 类级工具方法 this 指针,通过类名调用
函数内的静态局部变量 值持久化 只初始化一次,调用间保持值

二、类中的静态成员变量

2.1 基本用法

声明 :在类内用 static 声明

定义 :必须在类外用 类型 类名::变量名 = 初值; 分配内存

cpp 复制代码
class Counter
{
  private:
    static int count;      // 声明:这个变量属于类,不属于任何对象
  public:
    Counter()  { count++; }
    ~Counter() { count--; }
    int GetCount() { return count; }  // 所有对象访问的是同一个 count
};

int Counter::count = 0;    // 必须定义并初始化!

如果不写类外定义会怎样?

链接时报错:undefined reference to 'Counter::count'。类内只是声明,不分配内存

2.2 内存模型

cpp 复制代码
Counter a, b, c;    // 三个对象
成员 存储位置 份数
count (static) 全局数据区 1 份,所有对象共享
其他普通成员 每个对象内部 每对象 1 份

2.3 典型用途

用途 1:对象计数器

cpp 复制代码
class ECU
{
  private:
    static int activeInstances;
  public:
    ECU()  { activeInstances++; }
    ~ECU() { activeInstances--; }
    static int GetActiveCount() { return activeInstances; }
};
int ECU::activeInstances = 0;

// 随时查询当前有多少个 ECU 对象存活
write("Active ECUs: %d", ECU::GetActiveCount());

用途 2:全局配置参数

cpp 复制代码
class AppConfig
{
  public:
    static int baudRate;
    static char logPath[256];
};
int AppConfig::baudRate = 500000;
char AppConfig::logPath[256] = "C:\\logs\\";

// 任何地方直接读写
AppConfig::baudRate = 250000;

用途 3:共享资源句柄

cpp 复制代码
class Logger
{
  private:
    static dword fileHandle;     // 所有日志对象写入同一个文件
  public:
    static bool Open(char path[]);
    static void Write(char msg[]);
    static void Close();
};
dword Logger::fileHandle = 0;

三、类中的静态成员函数

3.1 基本用法

cpp 复制代码
class MathUtils
{
  public:
    static float ToFahrenheit(float celsius);
    static float ToCelsius(float fahrenheit);
};

float MathUtils::ToFahrenheit(float celsius)
{
  return celsius * 9.0 / 5.0 + 32.0;
}

// 调用:直接用类名,无需创建对象
float f = MathUtils::ToFahrenheit(25.0);

3.2 调用方式对比

cpp 复制代码
MathUtils::ToFahrenheit(25.0);      // ✅ 推荐:类名调用

MathUtils util;
util.ToFahrenheit(25.0);            // ⚠️ 也能用对象调,但不推荐

3.3 重要限制

静态成员函数没有 this 指针,因此:

能做什么 不能做什么
✅ 访问静态成员变量 ❌ 访问普通成员变量
✅ 调用其他静态成员函数 ❌ 调用普通成员函数
✅ 访问传入的参数 ❌ 使用 this
cpp 复制代码
class Test
{
  private:
    int normalVal;
    static int staticVal;
  public:
    static void Func()
    {
      staticVal = 10;      // ✅ 可以
      // normalVal = 5;    // ❌ 错误!没有 this,找不到属于哪个对象
    }
};

四、函数内的静态局部变量

4.1 基本用法

在函数内部用 static 声明的变量:只初始化一次,值在函数调用间保留

cpp 复制代码
void CountCalls()
{
  static int times = 0;    // 只在第一次调用时初始化为 0
  times++;
  write("Called %d times", times);
}

on key 'a'
{
  CountCalls();    // 第 1 次:Called 1 times
  CountCalls();    // 第 2 次:Called 2 times
  CountCalls();    // 第 3 次:Called 3 times
}

4.2 与普通局部变量的对比

cpp 复制代码
void NormalVar()
{
  int n = 0;       // 每次调用都重新初始化为 0
  n++;
  write("Normal: %d", n);    // 永远输出 1
}

void StaticVar()
{
  static int s = 0;  // 只在第一次调用时初始化为 0
  s++;
  write("Static: %d", s);    // 输出 1, 2, 3...
}

| 普通局部变量 | 静态局部变量 |
|-----------|----------|--------|
| 初始化 | 每次调用都初始化 | 只初始化一次 |
| 生命周期 | 函数返回即销毁 | 直到测量结束 |
| 作用域 | 函数内部 | 函数内部 |
| 值在调用间 | 不保留 | 保留 |

4.3 典型用途

用途 1:调用计数器

cpp 复制代码
void LogError(char msg[])
{
  static int errorCount = 0;
  errorCount++;
  write("Error #%d: %s", errorCount, msg);
}

用途 2:模拟"仅执行一次"的初始化

cpp 复制代码
void EnsureInitialized()
{
  static int done = 0;
  if (!done)
  {
    done = 1;
    // 这里的代码只会执行一次
    write("System initialized.");
  }
}

用途 3:缓存计算结果

cpp 复制代码
float GetExpensiveValue()
{
  static float cachedResult = -1;
  static int   cached = 0;
  
  if (!cached)
  {
    cached = 1;
    cachedResult = 3.1415926;   // 模拟耗时计算
  }
  return cachedResult;
}

五、三种 static 的对比总结

cpp 复制代码
class Demo
{
  private:
    static int shared;        // ① 类静态成员变量:所有对象共享
  public:
    static void Func()        // ② 类静态成员函数:无 this,类名调用
    {
      static int local = 0;   // ③ 函数内静态局部变量:值持久
      local++;
      shared++;
    }
};
int Demo::shared = 0;         // ① 的类外定义
类型 声明位置 调用/访问方式 生命周期 共享范围
① 静态成员变量 类内 类名::变量名对象.变量名 测量期间 该类的所有对象
② 静态成员函数 类内 类名::函数名()对象.函数名() 随时可调用 this,只能访问静态成员
③ 静态局部变量 函数内 仅在函数内部 测量期间 函数的各次调用之间