目录

C语言编程规范-常量

目录

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

}