C++传感器类设计:传递引用还是内嵌对象?
传感器类的组合/引用使用方案推荐
你当前使用的Sensor类定义如下:
class Sensor { public: int id; int sensorTypeVal; const char* name; SensorReading reading; // Constructor to initialize Sensor with id, type, and name Sensor(int id, int type, const char* name) : id(id), sensorTypeVal(type), name(name) {} // Initialize reading with default constructor // Constructor to initialize Sensor with id, type, name, and a SensorReading Sensor(int id, int type, const char* name, const SensorReading& reading) : id(id), sensorTypeVal(type), name(name), reading(reading) {} // Method to update the sensor reading void updateReading(const SensorReading& newReading) { reading = newReading; } };
针对你不想用包装模式重复属性的需求,以下是几种常规处理方案的分析和推荐:
一、传递Sensor引用(优先推荐)
- 适用场景:
Sensor对象由外部创建且生命周期更长(比如全局实例、上层模块管理),依赖类仅需访问传感器的属性或调用方法,不需要拥有该对象的所有权。 - 实现方式:在依赖类的构造函数中接收
Sensor&(需要修改读数时)或const Sensor&(仅读取属性时),并将引用作为类成员保存。 - 优点:
- 无对象拷贝,避免内存冗余;
- 直接访问原对象属性,无需重复定义;
- 符合C++中“所有权与使用权分离”的常见设计思路。
- 注意事项:必须保证被引用的
Sensor对象生命周期长于依赖类对象,否则会出现悬空引用(原对象销毁后,引用指向无效内存)。
二、内嵌Sensor对象(封装隐藏)
- 适用场景:依赖类需要完全拥有传感器对象,传感器的生命周期与依赖类绑定,且无需与其他类共享该Sensor实例。
- 实现方式:将
Sensor作为依赖类的私有成员变量,通过依赖类的成员函数暴露所需的传感器属性(例如int getSensorId() const { return sensor.id; }),避免直接暴露内部成员破坏封装。 - 优点:
- 对象生命周期管理简单,无悬空风险;
- 可通过封装隐藏Sensor的内部细节,仅对外暴露必要接口。
- 缺点:若多个类需要共享同一个Sensor实例,内嵌会导致多份副本,引发数据不一致;若Sensor对象体积较大,会增加依赖类的内存占用。
三、进阶方案:使用智能指针
- 适用场景:需要在多个类之间共享Sensor对象,且无法确定对象生命周期(例如动态创建的Sensor实例)。
- 实现方式:使用
std::shared_ptr<Sensor>作为依赖类的成员变量,构造时传递智能指针。 - 优点:自动管理对象生命周期,避免悬空引用和内存泄漏;多个类可共享同一Sensor实例,数据保持一致。
- 注意事项:需要理解智能指针的基本原理,建议新手先掌握前两种方案后再尝试。
新手友好建议
- 若Sensor由全局或顶层模块管理,优先选择引用传递,简单高效且无冗余;
- 若每个依赖类需要独立的Sensor实例,选择内嵌对象,生命周期管理更省心;
- 尽量避免使用裸指针,新手易出现内存问题,智能指针是更安全的替代方案但需要一定基础。
内容的提问来源于stack exchange,提问作者WouldRatherBuildAMotor
相关产品推荐
相关产品推荐

