C++语言编程规范-常量

01 C++还有搞头吗  

02 常量  

不变的值更易于理解、跟踪和分析,所以应该尽可能地使用常量代替变量,定义值的时候,应该把 const 作为默认的选项。

使用 const 常量取代宏

说明:宏是简单的文本替换,在预处理阶段时完成,运行报错时直接报相应的值;跟踪调试时也是显示值,而不是宏名;宏没有类型检查,不安全;宏没有作用域。

示例

    #define MAX_MSISDN_LEN (20) //不好的例子
    const int MAX_MSISDN_LEN = 20; //好的例子

    03  

    一组相关的整型常量应定义为枚举

    说明:之所以使用枚举,基于:

    ⚫ 

    枚举比#define 或 const int 更安全,因为编译器会检查参数值是否是否位于枚举取值范围内,从而避免错误发生。

    示例:

      //好的例子:
      enum DayOfWeek{sunday,monday, tuesday, wednesday, thursday, friday, saturday};  
      enum Color{black, blue, white, red, purple};  
      BOOL ColorizeCalendar(DayOfWeek today, Color todaysColor);  
      ColorizeCalendar(blue, sunday); //编译报错,Blue和Sunday位置错误
      //不好的例子:  
      const int sunday = 0;  
      const int monday = 1;  
      const int black = 0;  
      const int blue = 1;  
      BOOL ColorizeCalendar(int today, int todaysColor);  
      ColorizeCalendar(blue, sunday); //不会报错

      ⚫ 

      当枚举值需要对应到具体数值时,须在声明时显示赋值。否则不需要显式赋值,以避免重复赋值,降低维护(增加、删除成员)工作量。

      示例:

        //好的例子:S协议里定义的设备ID值,用于标识设备类型
        enum TDeviceType  
        {  
        DEV_UNKNOWN = -1,  
        DEV_DSMP = 0,  
        DEV_ISMG = 1,  
        DEV_WAPPORTAL = 2  
        };
        //好的例子:程序中用来标识会话状态的枚举定义
        enum TSessionState  
        {  
        SESSION_STATE_INIT,  
        SESSION_STATE_CLOSED,  
        SESSION_STATE_WAITING_FOR_RSP  
        };

        ⚫ 

        应当尽量避免枚举值重复,如必须重复也要用已定义的枚举来修饰,例如:

          typedef enum  
          {  
          RTCP_SR = 200,  
          RTCP_MIN_TYPE = RTCP_SR, //must be lowest known type  
          RTCP_RR = 201,
          RTCP_SDES = 202,  
          RTCP_BYE = 203,  
          RTCP_APP = 204,  
          RTCP_RTPFB = 205,  
          RTCP_PSFB = 206,  
          RTCP_XR = 207,  
          RTCP_RSI = 208,  
          RTCP_PUBPORTS = 209,  
          RTCP_MAX_TYPE = RTCP_PUBPORTS //must be highest known 
          } rtcp_type_t;

          04  

          不相关的常量,即使取值一样,也必须分别定义

          说明:一个常量只用来表示一个特定功能,即一个常量不能有多种用途。

          示例:

            //好的例子:协议A和协议B,手机号(MSISDN)的长度都是20。
            unsigned const int A_MAX_MSISDN_LEN = 20; 
            unsigned const int B_MAX_MSISDN_LEN = 20; 
            //或者使用不同的名字空间:
            namespace alib 
            const int MAX_MSISDN_LEN = 20; 
            namespace blib 
            const int MAX_MSISDN_LEN = 20; 
            }

            05  

            尽可能使用 const

            说明:

            在声明的变量或参数前加上关键字 const 用于指明变量值不可被篡改。

            成员函数加上 const 限定符表明该函数不会修改类成员变量的状态。

            使用 const 常见的场景:

            ⚫ 函数参数:传递引用时,如果函数不会修改传入参数, 该形参应声明为 const

              void printValue(const int& value) {  // 正确:不需要修改valuestd::cout << value << std::endl;// value = 10;  // 错误:不能修改const参数
              }
              int main() {int x = 5;const int y = 10;printValue(x);  // 可以传递非const变量printValue(y);  // 可以传递const变量printValue(42); // 可以传递临时值return 0;
              }

              ⚫ 成员函数:访问函数(如 get 函数);不修改任何数据成员的函数;未调用非 const 函数、未返回数据成员的非 const 指针或引用的函数。

                class MyClass {
                private:
                int value;
                mutable int cache;  // 即使在const函数中也可以修改
                mutable bool cacheValid;
                public:
                MyClass(int v) : value(v), cache(0), cacheValid(false) {}
                // 正确的const成员函数示例
                int getValue() const {
                return value;  // 只读取,不修改
                }
                int getValueWithCache() const {
                if (!cacheValid) {
                cache = value * 2;  // 修改mutable成员是允许的
                cacheValid = true;
                }
                return cache;
                }
                // 错误示例:这个函数修改了数据成员,不能是const
                void setValue(int v) {
                value = v;
                }
                // 错误示例:这个函数调用了非const成员函数,不能是const
                void updateAndGetValue() const {
                setValue(10);  // 错误:不能在const函数中调用非const函数
                }
                // 错误示例:返回了非const引用,不能是const
                int& getValueRef() const {
                return value;  // 错误:返回了非const引用
                }
                // 正确示例:返回const引用
                const int& getValueRef() const {
                return value;  // 正确:返回const引用
                }
                };
                int main() {
                const MyClass obj(5);
                int val = obj.getValue();  // 正确:可以在const对象上调用const成员函数
                // obj.setValue(10);       // 错误:不能在const对象上调用非const成员函数
                return 0;
                }

                ⚫ 数据成员:如果数据成员在对象构造之后不再发生变化, 可将其定义为 const

                  class Circle {
                  private:
                  const double radius;  // 半径在构造后不应改变
                  const double pi;      // π值恒定不变
                  double x, y;          // 位置可以改变
                  public:
                  Circle(double r, double x, double y)
                  : radius(r), pi(3.141592653589793), x(x), y(y) {
                  // 在构造函数初始化列表中初始化const成员
                  }
                  double getArea() const {
                  return pi * radius * radius;  // 可以使用const成员
                  }
                  void move(double newX, double newY) {
                  x = newX;  // 可以修改非const成员
                  y = newY;
                  }
                  // 错误示例:试图修改const成员
                  void setRadius(double newRadius) {
                  // radius = newRadius;  // 错误:不能修改const成员
                  }
                  };
                  int main() {
                  Circle c(5.0, 0.0, 0.0);
                  double area = c.getArea();  // 正确:可以访问const成员
                  // c.radius = 10.0;        // 错误:不能修改const成员
                  return 0;
                  }
                  class Circle {
                  private:
                  const double radius;  // 半径在构造后不应改变
                  const double pi;      // π值恒定不变
                  double x, y;          // 位置可以改变
                  public:
                  Circle(double r, double x, double y)
                  : radius(r), pi(3.141592653589793), x(x), y(y) {
                  // 在构造函数初始化列表中初始化const成员
                  }
                  double getArea() const {
                  return pi * radius * radius;  // 可以使用const成员
                  }
                  void move(double newX, double newY) {
                  x = newX;  // 可以修改非const成员
                  y = newY;
                  }
                  // 错误示例:试图修改const成员
                  void setRadius(double newRadius) {
                  // radius = newRadius;  // 错误:不能修改const成员
                  }
                  };
                  int main() {
                  Circle c(5.0, 0.0, 0.0);
                  double area = c.getArea();  // 正确:可以访问const成员
                  // c.radius = 10.0;        // 错误:不能修改const成员
                  return 0;
                  }

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

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

                  相关文章

                  【CS32L015C8T6】配置单片机PWM输出(内附完整代码及注释)

                  目录 前言&#xff1a; 一、CS32L015中定时器及PWM硬件资源介绍&#xff1a; 二、以CS32L015为例配置PWM步骤&#xff1a; 三、完整代码及注释 四、如果这篇文章能帮助到你&#xff0c;请点个赞鼓励一下吧ξ( ✿&#xff1e;◡❛)~ 前言&#xff1a; CS32L015 是一款内嵌 …

                  hive表不显示列注释column comment的问题解决

                  安装datasophon平台hive后&#xff0c;发现hive表的字段注释丢失了&#xff0c;表的注释没问题&#xff0c;csv格式的表没问题&#xff0c;只有parquet和orc的表有这个问题。查网上似乎没有这方面的问题。查看mysql表里面的中文注释也一切正常&#xff0c;后来经过多次研究才发…

                  【笔记】AI Agent发展趋势

                  前言 本章主要探讨了现在AI技术的发展趋势、大模型的一些局限性和小模型存在的必要性,然后引出了AI Agent的优势与发展趋势。 目标 学完本课程后,您将能够: 了解大模型的局限性; 了解小模型存在的必要性; 了解AI Agent的优势; 了解模型协同的技术。 目录 1.AI发…

                  ChatDOC工具测评:AI驱动PDF/Word文档处理,支持敏感内容隐私保护与表格提取分析

                  之前跟你们聊过用 Python 处理数据的 Pandas&#xff0c;今天换个更贴近日常办公的方向 —— 给你们安利一个 AI 文档处理工具「ChatDOC」&#xff0c;官网地址是https://www.chatdoc.com/&#xff0c;它能直接读取 PDF、Word 里的内容&#xff0c;你不用逐页翻文档找信息&…

                  Vue + fetchEventSource 使用 AbortController 遇到的“只能中止一次”问题解析与解决方案

                  前言 在前端项目中&#xff0c;使用 SSE&#xff08;Server-Sent Events&#xff09; 长连接去获取实时消息已经很常见了。像 fetchEventSource 这种封装好的工具&#xff0c;可以帮助我们轻松处理流式请求。 不过在实践中&#xff0c;我遇到了一个奇怪的问题&#xff1a;点击按…

                  Django get_or_create 方法详解

                  get_or_create 是 Django ORM 中的一个非常常用的方法&#xff0c;它用于获取数据库中的一个对象&#xff0c;如果该对象不存在&#xff0c;则创建一个新的对象并返回。 方法签名&#xff1a; Model.objects.get_or_create(defaultsNone, **kwargs)参数解释&#xff1a; defaul…

                  LangChain 文档问答系统中高级文本分割技术

                  告别语义断裂:LangChain 文档问答系统中高级文本分割技术深度指南 文章目录 引言:问题的根源——为何精准的文本分割是 RAG 系统的命脉? 第一部分:探本溯源——剖析 LangChain 默认分割器的“机械之困” 机制解析:语法驱动的“暴力”切分 问题场景化展示:语义、上下文与结…

                  Web2 vs Web3--差异一看就懂

                  互联网技术的浪潮不断推动着我们从Web2时代向Web3时代迈进。这两个时代在技术架构、用户体验、数据所有权等方面有着显著的差异。本文将为您详细解析Web2与Web3之间的差异&#xff0c;并探讨它们如何塑造我们的数字生活。 定义 Web2&#xff0c;即第二代互联网&#xff0c;以其…

                  深入解析MongoDB内部架构设计

                  MongoDB内部构造详解 MongoDB作为一款流行的NoSQL数据库&#xff0c;其内部构造设计独特且高效。以下从多个维度详细解析MongoDB的内部架构和核心组件。 一、整体架构 MongoDB采用分布式架构设计&#xff0c;主要包含以下核心组件&#xff1a;应用层&#xff1a;应用程序通过语…

                  ubuntu12.04安装opencalib手动标定并使用自己的数据

                  ubuntu22.04安装opencalib手动标定并使用自己的数据 一、OpenCalib的部署使用 1、基本信息 官网链接: https://github.com/PJLab-ADG/SensorsCalibration/tree/v0.2 (官网下载的zip文件是有问题的,不建议到官网下载) 参考链接: https://blog.csdn.net/qq_49959714/arti…

                  scss 转为原子css unocss

                  文章目录前言&#x1f3af; **方案一&#xff1a;混合模式 (推荐)**&#x1f3af; **方案二&#xff1a;语义化组件类**&#x1f3af; **方案三&#xff1a;CSS 模块化**&#x1f3af; **方案四&#xff1a;BEM 命名规范**&#x1f4a1; **推荐做法**前言 记录让c4 从scss 转为…

                  【面试题】生成式排序了解吗?

                  生成式排序是搜索排序的前沿方向&#xff0c;核心思想是利用生成式模型的能力来改善排序效果。 技术实现方式&#xff1a;序列到序列重排序 将候选文档列表作为输入序列使用encoder-decoder模型生成重排后的文档序列优势&#xff1a;能捕捉文档间的全局相关性生成式特征提取 使…

                  【系统架构设计(15)】软件架构设计一:软件架构概念与基于架构的软件开发

                  文章目录一、核心思想二、软件架构概念&#xff1a;系统设计的高级抽象三、软件架构设计与生命周期&#xff1a;架构在开发流程中的演进四、架构描述语言ADL&#xff1a;架构的标准化表达五、41视图&#xff1a;多角度的架构展现六、基于架构的软件开发概念&#xff1a;架构驱动…

                  文件系统-哈希结构文件

                  一、核心思想哈希文件的核心思想非常简单直接&#xff1a;通过一个计算&#xff08;哈希函数&#xff09;&#xff0c;将记录的键&#xff08;Key&#xff09;直接转换为该记录在磁盘上的物理地址&#xff08;通常是块地址&#xff09;&#xff0c;从而实现对记录的快速存取。它…

                  一文吃透 C#中异步编程Task

                  一文吃透 C#中异步编程Task 一、Task 是什么 二、推荐使用场景 三、Demo:Task 的核心用法 1. 最常用的启动方式Task.Run 2. task完成状态与结果获取 3. 多个任务怎么等?Wait/WaitAll/WaitAny 4. 任务想中途停掉?取消与异常处理 四、必备 API 速查表 五、避坑指南、注意事项 …

                  TDengine TIMETRUNCATE 函数用户使用手册

                  TDengine TIMETRUNCATE 函数用户使用手册 函数概述 TIMETRUNCATE 是 TDengine 中的一个时间处理标量函数&#xff0c;用于将时间戳按照指定的时间单位进行截断操作。该函数在时间数据聚合、分组和统计分析中非常有用&#xff0c;特别适用于智能电表等时序数据的分析场景。 语法…

                  KSZ8081寄存器介绍

                  一、寄存器概览KSZ8081MNX/RNB 支持 IEEE 802.3 标准的 MII 管理接口&#xff08;MDIO&#xff09;&#xff0c;寄存器地址范围为 0x00 - 0x1F&#xff0c;其中寄存器 0x00 - 0x08 为 IEEE 标准寄存器&#xff0c;0x09 - 0x1F 为扩展功能寄存器。寄存器按功能可分为基本控制与状…

                  力扣190:颠倒二进制位

                  力扣190:颠倒二进制位题目思路代码题目 颠倒给定的 32 位无符号整数number的二进制位。 思路 思路很简单&#xff0c;我们只需要得到number从低位到高位的每一个二进制位再把二进制位移到颠倒的res的对应二进制位即可&#xff0c;例如number的最低位为1那么res的最高位即1&a…

                  鸿蒙NEXT交互机制解析:从输入设备到手势响应的全面指南

                  深入探索鸿蒙NEXT的交互设计&#xff0c;掌握下一代人机交互核心技术在智能设备无处不在的今天&#xff0c;一个操作系统的交互设计质量直接影响着用户体验。鸿蒙NEXT作为华为推出的新一代操作系统&#xff0c;在交互设计上带来了许多创新和突破。本文将全面解析鸿蒙NEXT的交互…

                  通过IDEA写一个服务端和一个客户端之间的交互

                  服务端代码&#xff1a;WebSocketConfig代码package org.example.hufamessagedemo;import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.config.annotation.*;Configuration EnableWebSocket public class WebSocketConfig i…