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

news2025/5/13 9:50:32

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


一、const 数据成员

  1. 必须在初始化列表中初始化

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

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

    class B {
        static const int N = 100;  // 类内常量,若需要 ODR 定义,则在 cpp 中:
        // const int B::N; 
    };
    
    • static const 整数/枚举成员可在类内直接给初始值,不占实例空间。

二、const 成员函数

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

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

    const C c1(5);
    c1.getX();     // ✅ 可以调用 const 成员函数
    // c1.setX(7); // ❌ 错误:不能调用非 const 成员函数
    
  • 隐式 this 类型

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

三、const 对象

C obj1(3);      // 普通对象
const C obj2(4); // 常量对象,只能调用 const 成员函数
  • 只读语义obj2 的所有非 static 数据成员对于外部都是只读的。

  • 可与指针/引用混用

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

四、mutable 修饰符

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

class Logger {
    mutable std::ostream& os;  // 即使在 const 函数中也可修改
public:
    Logger(std::ostream& _os): os(_os) {}
    void log(const std::string& msg) const {
        os << msg << std::endl; // OK,os 是 mutable
    }
};
  • 场景:缓存、延迟初始化、统计访问次数等。

五、constexpr 与常量表达式

C++11 起,可将成员函数或构造函数声明为 constexpr,使其在编译期计算:

class Point {
    int x, y;
public:
    constexpr Point(int _x, int _y): x(_x), y(_y) {}
    constexpr int getX() const { return x; }
    constexpr int getY() const { return y; }
};

constexpr Point p(1,2);
static_assert(p.getX() == 1, "");  // 在编译期验证
  • 注意

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

六、与继承结合

struct Base {
    virtual void foo() const {
        // ...
    }
};
struct Derived : Base {
    void foo() const override { // 覆盖 const 成员函数
        // ...
    }
};
  • 覆盖时签名要一致:返回类型、参数列表后是否 const 都要相同,否则不构成覆盖。

七、注意事项汇总

  1. 忘记在初始化列表中初始化 const 成员

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

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

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

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

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

八、综合示例

#include <iostream>
#include <vector>

class Matrix {
    const int rows, cols;           // 必须初始化
    std::vector<double> data;       // 默认构造
    mutable bool           dirty;   // 缓存标志
public:
    // constexpr 构造 + 初始化列表
    constexpr Matrix(int r, int c)
      : rows(r), cols(c), data(r*c), dirty(true) {}

    // const 成员函数:只读访问
    double get(int i, int j) const {
        dirty = false;             // OK:dirty 是 mutable
        return data[i*cols + j];
    }
    // 非 const 成员函数:修改
    void set(int i, int j, double v) {
        data[i*cols + j] = v;
        dirty = true;
    }

    constexpr int getRows() const { return rows; }
    constexpr int getCols() const { return cols; }

    bool isDirty() const { return dirty; }
};

int main() {
    Matrix M(2,3);
    M.set(0,0,1.23);
    std::cout << M.get(0,0) << "\n";    // 可以修改 dirty
    std::cout << std::boolalpha 
              << M.isDirty() << "\n";   // false
    constexpr Matrix N(3,3);
    static_assert(N.getRows()==3, "");  // 编译期校验
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2374563.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【速写】KV-cache与解码的再探讨(以束搜索实现为例)

文章目录 1 Beam Search 解码算法实现2 实现带KV Cache的Beam Search解码3 关于在带kv-cache的情况下的use_cache参数 1 Beam Search 解码算法实现 下面是一个使用PyTorch实现的beam search解码算法&#xff1a; 几个小细节&#xff1a; 束搜索可以加入length_penalty&#…

(网络)应用层协议-HTTPS

1.HTTPS是什么&#xff1f; HTTPS是应用层的一种协议&#xff0c;是在HTTP的基础上进行了加密层的处理。 HTTP协议的内容都是按照文本的形式进行传输的&#xff0c;所以呢就很容易被别人知道传输的是什么。 我们在了解了TCP/IP之后是知道我们的数据在传输的过程中是通过路由器进…

vue3: pdf.js 3.4.120 using javascript

npm install pdfjs-dist3.4.120 项目结构&#xff1a; pdfjsViewer.vue <template><div><div v-if"loading" class"flex justify-center items-center py-8"><div class"animate-spin rounded-full h-12 w-12 border-b-2 borde…

想实现一个基于MCP的pptx生成系统架构图【初版实现】

技术栈:Python + MCP协议 + python-pptx + FastMCP 核心创新点:通过MCP协议实现PPTX元素的动态化生成与标准化模板管理 当前还是个半成品,后续持续更新。 主要先介绍一下思路。 一、MCP协议与系统设计原理 1.1 为什么选择MCP? 标准化工具调用:通过MCP将PPTX元素生成逻辑封…

PyTorch Lightning实战 - 训练 MNIST 数据集

MNIST with PyTorch Lightning 利用 PyTorch Lightning 训练 MNIST 数据。验证梯度范数、学习率、优化器对训练的影响。 pip show lightning Version: 2.5.1.post0Fast dev run DATASET_DIR"/repos/datasets" python mnist_pl.py --output_grad_norm --fast_dev_run…

力扣2094题解

记录&#xff1a; 2025.5.12 题目&#xff1a; 思路&#xff1a; 暴力遍历。 解题步骤&#xff1a; 1.统计数字出现次数&#xff1a;使用数组cnt来记录输入数组中每个数字的出现次数。 2.生成三位偶数&#xff1a;通过循环从100开始&#xff0c;每次递增2&#xff0c;生成…

DHCP自动分配IP

DHCP自动分配IP 练习1 路由器 Router>en Router#conf t Router(config)#ip dhcp pool ip10 //创建DHCP地址池 Router(dhcp-config)#network 192.168.20.0 255.255.255.0 // 配置网络地址和子网掩码 Router(dhcp-config)#default-router 192.168.20.254 //配置默认网关 Rou…

【CF】Day57——Codeforces Round 955 (Div. 2, with prizes from NEAR!) BCD

B. Collatz Conjecture 题目&#xff1a; 思路&#xff1a; 简单模拟 很简单的模拟&#xff0c;我们只需要快速的找到下一个离 x 最近的 y 的倍数即可&#xff08;要大于 x&#xff09; 这里我们可以这样写 add y - (x % y)&#xff0c;这样就知道如果 x 要变成 y 的倍数还要…

(done) 补充:xv6 的一个用户程序 init 是怎么启动的 ?它如何启动第一个 bash ?

先看 main.c 从函数名来看&#xff0c;比较相关的就 userinit() 和 scheduler() #include "types.h" #include "param.h" #include "memlayout.h" #include "riscv.h" #include "defs.h"volatile static int started 0;//…

超详细讲解C语言转义字符\a \b \r \t \? \n等等

转义字符 C语言有一组字符很特殊&#xff0c;叫做转义字符&#xff0c;顾名思义&#xff0c;改变原来的意思的字符。 1 \? ??)是一个三字母词&#xff0c;在以前的编译器它会被编译为] (??会被编译为[ 因此在以前输入(are you ok ??)就会被编译为are you ok ] 解决这个…

SpringBoot校园失物招领信息平台

SpringBoot校园失物招领信息平台 文章目录 SpringBoot校园失物招领信息平台1、技术栈2、项目说明2.1、登录注册2.2、管理员端截图2.3、用户端截图 3、核心代码实现3.1、前端首页3.2、前端招领广场3.3、后端业务处理 1、技术栈 本项目采用前后端分离的架构&#xff0c;前端和后…

rust 全栈应用框架dioxus server

接上一篇文章dioxus全栈应用框架的基本使用&#xff0c;支持web、desktop、mobile等平台。 可以先查看上一篇文章rust 全栈应用框架dioxus&#x1f448; 既然是全栈框架&#xff0c;那肯定是得有后端服务的&#xff0c;之前创建的服务没有包含后端服务包&#xff0c;我们修改…

西安交大多校联训NOIP1模拟赛题解

西安交大多校联训NOIP1模拟赛题解 T1 秘境形式化题意思路代码&#xff08;丑陋&#xff09; T2 礼物形式化题意思路代码&#xff08;实现&#xff09; T3 小盒子的数论形式化题意思路代码&#xff08;分讨&#xff09; T4 猫猫贴贴(CF997E)形式化题意思路代码&#xff08;深奥&…

数据结构(三)——栈和队列

一、栈和队列的定义和特点 栈&#xff1a;受约束的线性表&#xff0c;只允许栈顶元素入栈和出栈 对栈来说&#xff0c;表尾端称为栈顶&#xff0c;表头端称为栈底&#xff0c;不含元素的空表称为空栈 先进后出&#xff0c;后进先出 队列&#xff1a;受约束的线性表&#xff0…

若依定制pdf生成实战

一、介绍 使用 Java Apache POI 将文字渲染到 Word 模板是一种常见的文档自动化技术&#xff0c;广泛应用于批量生成或定制 Word 文档的场景。使用aspose可以将word转成pdf从而达到定制化pdf的目的。 参考文档&#xff1a;java实现Word转Pdf&#xff08;Windows、Linux通用&a…

c++STL-vector的模拟实现

cSTL-vector的模拟实现 vector的模拟实现基本信息构造函数析构函数返回容量&#xff08;capacity&#xff09;返回元素个数&#xff08;size&#xff09;扩容&#xff08;reserve和resize&#xff09;访问&#xff08;[]&#xff09;迭代器&#xff08;**iterator**&#xff09…

在 Elasticsearch 中连接两个索引

作者&#xff1a;来自 Elastic Kofi Bartlett 解释如何使用 terms query 和 enrich processor 来连接 Elasticsearch 中的两个索引。 更多有关连接两个索引的查询&#xff0c;请参阅文章 “Elastic&#xff1a;开发者上手指南” 中的 “丰富数据及 lookup” 章节。 Elasticsea…

使用 Watt toolkit 加速 git clone

一、前言 Watt toolkit 工具是我经常用于加速 GitHub 网页和 Steam 游戏商店访问的工具&#xff0c;最近想加速 git clone&#xff0c;发现可以使用 Watt toolkit 工具的代理实现。 二、查看端口 我这里以 Ubuntu 为例&#xff0c;首先是需要将加速模式设置为 System&#xff1…

应急响应靶机——WhereIS?

用户名及密码&#xff1a;zgsf/zgsf 下载资源还有个解题.exe: 1、攻击者的两个ip地址 2、flag1和flag2 3、后门程序进程名称 4、攻击者的提权方式(输入程序名称即可) 之前的命令&#xff1a; 1、攻击者的两个ip地址 先获得root权限&#xff0c;查看一下历史命令记录&#x…

Docke容器下JAVA系统时间与Linux服务器时间不一致问题解决办法

本篇文章主要讲解&#xff0c;通过docker部署jar包运行环境后出现java系统内时间与服务器、个人电脑真实时间不一致的问题原因及解决办法。 作者&#xff1a;任聪聪 日期&#xff1a;2025年5月12日 问题现象&#xff1a; 说明&#xff1a;与实际时间不符&#xff0c;同时与服务…