capl--static
一、static 总览
| 使用位置 | 核心作用 | 关键行为 |
|---|---|---|
| 类的静态成员变量 | 类级共享数据 | 所有对象共享一份,类外必须定义 |
| 类的静态成员函数 | 类级工具方法 | 无this指针,通过类名调用 |
| 函数内的静态局部变量 | 值持久化 | 只初始化一次,调用间保持值 |
二、类中的静态成员变量
2.1 基本用法
声明:在类内用static声明
定义:必须在类外用类型 类名::变量名 = 初值;分配内存
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 内存模型
Counter a, b, c; // 三个对象| 成员 | 存储位置 | 份数 |
|---|---|---|
count(static) | 全局数据区 | 1 份,所有对象共享 |
| 其他普通成员 | 每个对象内部 | 每对象 1 份 |
2.3 典型用途
用途 1:对象计数器
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:全局配置参数
class AppConfig { public: static int baudRate; static char logPath[256]; }; int AppConfig::baudRate = 500000; char AppConfig::logPath[256] = "C:\\logs\\"; // 任何地方直接读写 AppConfig::baudRate = 250000;用途 3:共享资源句柄
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 基本用法
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 调用方式对比
MathUtils::ToFahrenheit(25.0); // ✅ 推荐:类名调用 MathUtils util; util.ToFahrenheit(25.0); // ⚠️ 也能用对象调,但不推荐3.3 重要限制
静态成员函数没有this指针,因此:
| 能做什么 | 不能做什么 |
|---|---|
| ✅ 访问静态成员变量 | ❌ 访问普通成员变量 |
| ✅ 调用其他静态成员函数 | ❌ 调用普通成员函数 |
| ✅ 访问传入的参数 | ❌ 使用this |
class Test { private: int normalVal; static int staticVal; public: static void Func() { staticVal = 10; // ✅ 可以 // normalVal = 5; // ❌ 错误!没有 this,找不到属于哪个对象 } };四、函数内的静态局部变量
4.1 基本用法
在函数内部用static声明的变量:只初始化一次,值在函数调用间保留。
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 与普通局部变量的对比
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:调用计数器
void LogError(char msg[]) { static int errorCount = 0; errorCount++; write("Error #%d: %s", errorCount, msg); }用途 2:模拟“仅执行一次”的初始化
void EnsureInitialized() { static int done = 0; if (!done) { done = 1; // 这里的代码只会执行一次 write("System initialized."); } }用途 3:缓存计算结果
float GetExpensiveValue() { static float cachedResult = -1; static int cached = 0; if (!cached) { cached = 1; cachedResult = 3.1415926; // 模拟耗时计算 } return cachedResult; }五、三种 static 的对比总结
class Demo { private: static int shared; // ① 类静态成员变量:所有对象共享 public: static void Func() // ② 类静态成员函数:无 this,类名调用 { static int local = 0; // ③ 函数内静态局部变量:值持久 local++; shared++; } }; int Demo::shared = 0; // ① 的类外定义| 类型 | 声明位置 | 调用/访问方式 | 生命周期 | 共享范围 |
|---|---|---|---|---|
| ① 静态成员变量 | 类内 | 类名::变量名或对象.变量名 | 测量期间 | 该类的所有对象 |
| ② 静态成员函数 | 类内 | 类名::函数名()或对象.函数名() | 随时可调用 | 无this,只能访问静态成员 |
| ③ 静态局部变量 | 函数内 | 仅在函数内部 | 测量期间 | 函数的各次调用之间 |
