const修饰符全面理解

const修饰符就是为了将变量声明为不可变的常量,使程序更加的健壮。

(1)为什么define应该用const enum inline来替代(effective C++):

const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误(边际效应) 。

define作用于预编译阶段,也就是说在预编译阶段把所有define的常量替换为相应字符,常量没有进入符号表,这样如果出错编译器只会提示相应字符出错不会 不好进行判断,所以define声明的常量应该用const或者枚举替代来声明常量,这样才能加入到字符表,出错很容易调试。

define声明的形式函数的宏,应该用inline 模板函数进行替代,因为宏不具有安全性,其并不是一个统一的整体,应用内联函数替代。

      小插曲,enum与const定义常量是的优缺点:const与enum各有优缺点,最大的区别就是enum只能用于定义整数,而不能定义浮点数;而对于定义逻辑关系较近的一组符号常量时比较适合使用enum,不适合使用const.

(2)const修饰类的数据成员:

class A 



    const int size; 

    … 



const 数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的。因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。所以不能在类 声明中初始化const数据成员,因为类的对象未被创建时,编译器不知道const 数据成员的值是什么。如 

class A 



const int size = 100;    //错误 

int array[size];        //错误,未知的size 



const数据成员的初始化只能在类的构造函数的初始化表中进行。要想建立在整个类中都恒定的常量,应该用类中的枚举常量来实现。如 
class A 

{… 

enum {size1=100, size2 = 200 }; 

int array1[size1]; 

int array2[size2]; 


枚举常量不会占用对象的存储空间,他们在编译时被全部求值。但是枚举常量的隐含数据类型是整数,其最大值有限,且不能表示浮点数。 

(3)const修饰类的成员函数:

一般放在函数体后,形如:void fun() const; 

任何不会修改数据成员的函数都因该声明为const类型。如果在编写const成员函数时,不慎修改了数据成员,或者调用了其他非const成员函数,编译器将报错,这大大提高了程序的健壮性。l另外,const修饰的成员函数只能调用const成员函数如: 

class Stack 



public: 

      void Push(int elem); 

      int Pop(void); 

      int GetCount(void) const;  //const 成员函数 

private: 

      int m_num; 

      int m_data[100]; 

}; 

int Stack::GetCount(void) const 



  ++m_num;              //编译错误,企图修改数据成员m_num 

  Pop();                    //编译错误,企图调用非const函数 

  Return m_num; 


(4)const对象:

常对象是指对象的数据成员的值在对象被调用时不能被改变。常对象必须进行初始化,且不能被更新。不能通过常对象调用普通成员函数,但是可以通过普通对象调用常成员函数。常对象只能调用常成员函数。

class A{
private:
     int w,h;
public:
     int getArea() const
     {   
         return w*h;
     }
     int getW(){ return w;}

     void setWH(int x,int y) {w=x,h=y;}
     A(int x,int y){w=x,h=y;}
     A(){;}//本例中不能省略
};

 
void main()
{   
     A a;//非常对象可以不初始化
     a.setWH(3,9);
     A const b;    //常对象必须声明的同时初始化,正确的是 A const b(3,6)。
     b.setWH(3,7); // 假如上面改正后用这一句,还是错误应为b是常对象不能调用非常成员函数,切其值调用时不能改变,setWH()
     cout<< a.getArea()<<endl<< b.getArea()<<c.getArea();
     system("pause");

也就是说常对象在初始化的时候必须通过构造函数进行初始化,并且const对象只能调用cosnt函数,这样可以保证其健壮性,确保const对象没有对

数据成员进行任何的修改。

(5)const 修饰指针:

如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于星号的 右侧,const就是修饰指针本身,即指针本身是常量(efficetve C++)。


(6) const 修饰函数:

     i:const修饰函数参数,此处需要谨记就是说内置数据类型(如int double char等)应该直接用值传递的方式,这样简单易懂,效率高(函数内部维持此变量的拷贝);如果为非内置数据类型,如struct或class等,函数传参应该是const 指针 或者cosnt 引用,最好用const引用,因为引用比指针更加的安全。如void Func(A a)改为void Func(const A &a) 或者Func(const A* a).(当然此处有一个前提就是传递过来的参数不进行改变才加const,如果改变的话就不加const修饰符)。

    ii:const修饰函数返回值。只需要考虑特殊的返回const指针这种情况。如果给采用“指针传递”方式的函数返回值加const修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。onst char * GetString(void); 

如下语句将出现编译错误: 

char *str=GetString(); 

正确的用法是: 

const char *str=GetString(); 

同时,str指针可以指向其他字符串,但是*str的值不能被修改。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值