只读属性场景下必须只提供getter且数据成员严格私有。返回const引用或值,函数声明末尾加const,禁止public/protected成员变量,构造时初始化后仅允许查询。

只读属性场景下必须只提供 getter
当类内某个状态对外暴露后,业务逻辑要求它不可被外部修改时,就该只声明 get_XXX() 而不写 set_XXX()。这不是偷懒,而是明确表达“这个值由类自己控制生命周期和变更时机”。比如对象创建后就固定的 ID、计算得出的哈希值、或依赖内部多个字段推导出的摘要信息。
getter 返回 const 引用或值,避免意外可写
只提供 getter 时,返回类型选错会导致封装失效。常见错误是返回非 const 引用:std::string& getName() —— 调用方能直接改内部字符串;或者返回指针,让外部拿到地址后绕过控制逻辑。
- 安全做法:返回
const std::string&(避免拷贝,又禁止修改)或std::string(值语义,完全隔离) - 绝对不要:返回
std::string&、std::string*或std::string&& - 注意 const 正确性:函数声明末尾必须加
const,否则无法在 const 对象上调用
误用 protected 或 public 成员变量会彻底绕过 getter 控制
即使你写了干净的 getAge() const,只要底层变量 m_age 是 public 或 protected,用户就能直接写 p.m_age = -1,所有校验和逻辑形同虚设。
- 检查点:所有数据成员必须严格放在
private:块中 - 反例:
public: int m_age;或protected: std::string m_name;—— 这不是封装,是裸露 - 哪怕变量声明为
const int MAX_SIZE = 100;,只要它在public:下,外部就能取地址、模板特化窥探,破坏边界
构造时初始化 + 后续只读访问是典型模式
很多只读字段其实在构造函数里就定死了,之后只供查询。这时候 setter 不仅没必要,还可能误导使用者以为可以修改。
立即学习“C++免费学习笔记(深入)”;
- 示例:一个
Config类加载配置文件后,m_config_path就固定了,只提供const std::string& getConfigPath() const - 若强行加
setConfigPath(),就得处理路径变更引发的缓存失效、重载、线程安全等问题——而这些本不该由调用方承担 - 真正需要运行时更新的字段,才值得引入 setter 及配套的校验/通知/同步逻辑
protected 都不能松口。


















