C++ 类的 static 成员函数

我用最简单、最直观、和你代码一模一样的场景 ,给你把 static 讲得明明白白!

先记一句话

普通成员 = 属于某个对象(每个传感器自己的) 静态成员 = 属于整个类(大家共用的)


1. 普通成员函数(不带 static)

cpp

运行

复制代码
class SensorSht40 {
    void ReadTask(void *arg); 
};

特点:

  1. 属于某一个传感器对象
  2. 必须通过 sensor->ReadTask() 调用
  3. 自带 this 指针(知道自己是哪个传感器)
  4. 能直接访问私有变量 _temperature

cpp

运行

复制代码
SensorSht40 sensor1;
SensorSht40 sensor2;

sensor1.ReadTask(); // 是 sensor1 的
sensor2.ReadTask(); // 是 sensor2 的

2. 静态成员函数(带 static)

cpp

运行

复制代码
class SensorSht40 {
    static void readTaskWrapper(void *arg);
};

特点:

  1. 不属于任何传感器!属于整个类
  2. 没有 this 指针
  3. 可以直接调用,不需要对象
  4. 能访问私有成员

cpp

运行

复制代码
// 直接用类调用,不需要传感器对象!
SensorSht40::readTaskWrapper(arg);

3. 为什么 FreeRTOS 必须用 static?

FreeRTOS 创建任务要求函数格式必须是:

cpp

运行

复制代码
void (*task_fn)(void *arg);

普通成员函数,编译器会变成:

cpp

运行

复制代码
void ReadTask(SensorSht40* this, void *arg);

❌ 多了一个 this → 格式不匹配 → 报错!

静态函数编译器就是:

cpp

运行

复制代码
void readTaskWrapper(void *arg);

✅ 完全匹配 → 可以创建任务!


4. 最经典的例子(你代码里的用法)

任务包装函数 必须 static

cpp

运行

复制代码
class SensorSht40 {
private:
    float _temperature;

    // 真正的任务(每个传感器自己的)
    void ReadTask(void *arg) {
        while(1) {
            _temperature = read();
            vTaskDelay(1000);
        }
    }

    // 👇 静态包装函数(通用,无this)
    static void readTaskWrapper(void *arg) {
        SensorSht40* sensor = (SensorSht40*)arg;
        sensor->ReadTask(); // 调用真正的任务
    }
};

创建任务

cpp

运行

复制代码
xTaskCreate(readTaskWrapper, ..., this, ...);

流程:

  1. 任务启动 → 调用 readTaskWrapper
  2. 它是 static → 符合 FreeRTOS 要求
  3. 从 arg 拿到传感器对象
  4. 调用真正的 sensor->ReadTask()

5. 静态变量例子(共用数据)

cpp

运行

复制代码
class SensorSht40 {
    static int sensor_count;
};

// 所有传感器共用一个 count
SensorSht40 s1;
SensorSht40 s2;

s1.count = 1;
s2.count = 2; 
// s1.count 也变成 2!

6. 超级总结(3 句话背会)

  1. static 成员属于类,不属于对象
  2. static 函数没有 this 指针 → 能当 FreeRTOS 任务
  3. static 函数能访问 private → 完美封装

对应你现在的代码

cpp

运行

复制代码
static void readTaskWrapper(void *arg);

这就是 C++ + FreeRTOS 最标准、最安全、最正确的写法。

如果你愿意,我可以给你一个万能模板,以后所有传感器、电机、屏幕类都能直接复制使用!

相关推荐
傲世仙尊3 分钟前
继承-类设计层次复用切片转换与菱形继承的死结
c++
架构师伯子明5 分钟前
FFmpeg C++学习(一):编译和demo
开发语言·c++·学习
纪念 22929 分钟前
C++算法(六)
开发语言·c++·算法
ShineWinsu1 小时前
对于Qt:QCheckBox常见属性的详细解析
c++·qt·面试·笔试·gui·qcheckbox·多选框
AI的探索之旅1 小时前
97 个 OpenCV 实例(三十七):二维码识别,一张图四个码的陷阱
c++·opencv·计算机视觉
UIU1142 小时前
P16237 [蓝桥杯 2026 省 B] 应急布线
数据结构·c++·算法·蓝桥杯
raindayinrain2 小时前
c++设计模式
开发语言·c++·设计模式
旖旎夜光2 小时前
LeetCode 315: 算右侧小于当前元素的个数(归并排序) —— 题解
c++·学习·算法·leetcode·排序算法
D e re k ZH2 小时前
保序回归:从 PAVA 到可并堆的单调约束优化
c++·算法·数据挖掘·回归·kotlin
青少儿编程课堂2 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:字典树前缀树与单词检索统计
c++·python·算法·bfs·信息学竞赛