学逆向论坛

找回密码
立即注册

只需一步,快速开始

发新帖

779

积分

0

好友

98

主题
发表于 2025-5-22 11:38:36 | 查看: 141| 回复: 0
本帖最后由 jinchanchan 于 2025-5-22 11:42 编辑

下面将从const 成员、const 成员函数、const 对象、mutable、constexpr 等方面,逐一详解 C++ 类中常见的 const 用法及注意事项,并配合示例。

一、const 数据成员
必须在初始化列表中初始化

<p>class A {</p><p>    const int x;    // const 成员</p><p>public:</p><p>    A(int v) : x(v) { }   // ❌ 合法:初始化列表中初始化</p><p>    // A(int v) { x = v; } // ❌ 错误:无法在函数体内赋值</p><p>};</p>

不可修改

一旦初始化,之后在对象生存期内不能再改变。
可用于对外保证成员不被篡改。
与静态成员结合

<p>class B {</p><p>    static const int N = 100;  // 类内常量,若需要 ODR 定义,则在 cpp 中:</p><p>    // const int B::N; </p><p>};</p>

static const 整数/枚举成员可在类内直接给初始值,不占实例空间。

二、const 成员函数
在成员函数后添加 const,表明该函数不会修改任何非 mutable 成员,也不会调用非 const 成员函数。

<p>class C {</p><p>    int x;</p><p>public:</p><p>    C(int v): x(v) {}</p><p>    int  getX() const {      // 常量成员函数</p><p>        return x;             // 只能访问 x,不可修改</p><p>    }</p><p>    void setX(int v) {       // 非 const 函数</p><p>        x = v;</p><p>    }</p><p>};</p>

调用约束

<p>const C c1(5);</p><p>c1.getX();     // ✅ 可以调用 const 成员函数</p><p>// c1.setX(7); // ❌ 错误:不能调用非 const 成员函数</p>


隐式 this 类型

在 const 成员函数中,this 的类型为 const C*,保证不可修改成员。

三、const 对象
<p>C obj1(3);      // 普通对象</p><p>const C obj2(4); // 常量对象,只能调用 const 成员函数</p>

只读语义:obj2 的所有非 static 数据成员对于外部都是只读的。

可与指针/引用混用:

<p>void foo(const C& c);</p><p>foo(obj1);    // OK,将 obj1 作为只读参数</p>


四、mutable 修饰符
当你希望在 const 成员函数中仍然修改某些成员,可将它们声明为 mutable:

<p>class Logger {</p><p>    mutable std::ostream& os;  // 即使在 const 函数中也可修改</p><p>public:</p><p>    Logger(std::ostream& _os): os(_os) {}</p><p>    void log(const std::string& msg) const {</p><p>        os << msg << std::endl; // OK,os 是 mutable</p><p>    }</p><p>};</p>

场景:缓存、延迟初始化、统计访问次数等。

五、constexpr 与常量表达式
C++11 起,可将成员函数或构造函数声明为 constexpr,使其在编译期计算:

<p>class Point {</p><p>    int x, y;</p><p>public:</p><p>    constexpr Point(int _x, int _y): x(_x), y(_y) {}</p><p>    constexpr int getX() const { return x; }</p><p>    constexpr int getY() const { return y; }</p><p>};</p><p></p>
<p>constexpr Point p(1,2);</p><p>static_assert(p.getX() == 1, "");  // 在编译期验证</p>


注意:

constexpr 成员函数 必须 同时 是 const(除了构造函数)。
只有在满足编译期求值规则时才真正成为常量表达式。

六、与继承结合
<p>struct Base {</p><p>    virtual void foo() const {</p><p>        // ...</p><p>    }</p><p>};</p>
<p>struct Derived : Base {</p><p>    void foo() const override { // 覆盖 const 成员函数</p><p>        // ...</p><p>    }</p><p>};</p>


覆盖时签名要一致:返回类型、参数列表后是否 const 都要相同,否则不构成覆盖。

七、注意事项汇总
忘记在初始化列表中初始化 const 成员

会导致编译错误。
在 const 成员函数中尝试修改非 mutable 成员

编译器会报错,防止越界修改。
constexpr 函数应当尽量简单

包含循环与分支也支持,但要遵守常量表达式的限制。
不要滥用 mutable

可能破坏对象的逻辑常量性(logical constness),只在真正需要缓存、延迟初始化时使用。
接口设计

对于只读操作,应当标记为 const;有副作用的操作,要去除 const,让常量对象无法调用。

八、综合示例

C++中类中const知识应用详解

C++中类中const知识应用详解

————————————————

转载自:点云SLAM

温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的认可,还可以获得学币奖励,请尊重他人的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【投诉建议】板块发帖举报。

小黑屋|手机版|站务邮箱|学逆向论坛 ( 粤ICP备2021023307号 )|网站地图

GMT+8, 2025-6-1 09:14 , Processed in 0.125855 second(s), 37 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表