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) {  // 正确:不需要修改value
                  std::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;
                  }

                  更多推荐