C/C++之const关键字

来源:互联网 发布:淘宝直通车怎么开烟台 编辑:程序博客网 时间:2024/05/23 20:07

1.const修饰常量

功能与#define相同。

#define  MAX  10;

const  int  MAX = 10;

但相比于使用#define定义的宏常量,const常量有数据类型,编译器会对其进行  数据类型检查,而宏常量只是简单的字符替换,编译器不会对其进行数据类型检查。

在另一个文件中引用const常量:

extern const int MAX; //正确,MAX在其他文件中已定义

extern const int MAX = 10//错误,MAX在其他文件中已定义,不可再赋值。

2.const修饰变量

声明变量只读,不可被修改。

const  int  mm = 5;

注意:const变量定义时,必须初始化,并且以后不可被修改。

其实,上面的第1中情况,准确的讲,也应该属于第二种情况,这里分开来讨论主要是根据其与#define定义的宏常量等价来分的,因为第一种情况即const常量类似宏常量一般定义在头文件中的。

const与指针

指针常量:指针本身是常量,不可变。

int  a;

int  * const  pt = &a; //pt是常量,定义时必须初始化

指向常量的指针:指针本身可变,指向的变量不可变。

const  int * pt;  //指针本身不是const的,不用初始化。

int  const * pt;  //与上一个等价。

注意:要区别是指针常量还是指向常量的指针,其实根据定义很好区别,如果const修饰的是*pt,则pt是指向常量的指针,const修饰的是pt,则pt是指针常量。

3.const修饰函数的参数

const不用于修饰输出参数,因为输出参数一般是要通过函数来改变的。

对于输入参数,如果输入参数采用”指针传递”,那么加const可防止意外地改变该指针,起到保护作用。

如:StrCopy(char * strDst, const char *strSrc);

strSrc是输入参数,strDst是输出参数,加上const后,函数体内如有语句修改strSrc值,编译器将报错。

如果输入参数,若采用”值传递”,因函数调用时,函数将自动用临时变量复制该参数,函数不会对该参数操作,所以加const也没用。

对于非内部数据类型的参数,如void  Fun( A  a)函数,在调用时,将产生A类型的临时变量复制a,而临时对象的创建将调用构造函数、拷贝构造函数、析构函数将消耗时间。为了提高效率,可以将函数改为void  Fun( A  &a),因为”引用传递”仅借用参数的别名,不用产生临时对象。但”引用传递”可能改变参数a的值,这可能不是我们期望的,所以可以改成这样void  Fun(const A  &a).

那对于void  Fun(int  b)是否有必要像上面一样改呢?,其实完全没有必要,因为对于内部数据类型,根本不存在构造函数和析构函数。

因此我们可以总结如下:


4.类中的const

4.1 const数据成员

const数据成员只在某个对象生存期内是常量,而对整个类而言是可变的。因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。

不能在类的声明中初始化const数据成员,只能在构造函数的初始化表中进行。

如下两种方式均是错误的:

(1)

class A{public:const int con = 10; //错误,类声明时初始化。};
(2)
class A{public:A(int c);const int con;};A::A(int c){con = c;}
正确的方式应该如下:

class A{public:A(int c);const int con;};A::A(int c):con(c){}void main(void){const A(4);}

既然const数据成员对整个类而言是可变的,那怎样建立在整个类中都是恒定的常量呢?我们可以采用枚举常量来实现。

class A{public:enum{SIZE1 = 10,SIZE2 = 20};  //枚举常量int array1[SIZE1];int array2[SIZE2];};

枚举常量不会占用对象的存储空间,它在编译时被全部求值。

4.2 const成员函数

任何不会修改类得数据成员的函数都应该声明为const类型,而任何const类型成员函数,不得修改数据成员和调用非const类型的成员函数。类似于static成员函数只能使用static数据成员和调用static成员函数。

注意:在const成员函数的声明与定义中,const关键字放在最后的。

class A{public:void fun1() const;//const成员函数声明};A::fun1() const{...........; //不能改变数据成员,不能调用非const成员函数}

5.const修饰对象/对象指针/对象引用

任何const对象只能使用const成员函数,不能调用非const成员函数,因为非const成员函数有可能改变数据成员。const对象指针/对象引用类似。

class A{public:void fun1();void fun2() const;};A::fun1(){}A::fun2() const{}void main(void){const A a;a.fun1(); //错误,const对象调用非const成员函数a.fun2();  //正确}








原创粉丝点击