C++const用法总结 (二)

2014-11-24 01:35:50 · 作者: · 浏览: 6
onst;
const A operator+(const A &) const;
private:
int num1;
mutable int num2;
const size_t size;
};
1.修饰成员变量
const size_t size; // 对于const的成员变量,[1]必须在构造函数里面进行初始化;[2]只能通过初始化成员列表来初始化;[3]试图在构造函数体内对const成员变量进行初始化会引起编译错误。
例如:
A::A(size_t sz):size(sz) // ok:使用初始化成员列表来初始化
{
}
A::A(size_t sz)
2.修饰类成员函数
void func() const; // const成员函数中不允许对数据成员进行修改,如果修改,编译器将报错。如果某成员函数不需要对数据成员进行修改,最好将其声明为const 成员函数,这将大大提高程序的健壮性。
const 为函数重载提供了一个参考
class A
{
public:
void func(); // [1]:一个函数
void func() const; // [2]:上一个函数[1]的重载
……
};
A a(10);
a.func(); // 调用函数[1]
const A b(100);
b.func(); // 调用函数[2]
如何在const成员函数中对成员变量进行修改???
下面提供几种方式(只提倡使用第一种,其他方式不建议使用)
(1)标准方式:mutable
class A
{
public:
A::A(int i):m_data(i){}
void SetValue(int i){ m_data = i; }
private:
mutable int m_data; // 这里处理
};
(2)强制转换:static_cast
class A
{
public:
A::A(int i):m_data(i){}
void SetValue(int i)
{ static_cast(m_data) = i; } // 这里处理
private:
int m_data;
};
(3)强制转换:const_cast
class A
{
public:
A::A(int i):m_data(i){}
void SetValue(int i)
{ const_cast(this)->m_data = i; } // 这里处理
private:
int m_data;
};
(4)使用指针:int *
class A
{
public:
A::A(int i):m_data(i){}
void SetValue(int i)
{ *m_data = i; } // 这里处理
private:
int *m_data;
};
(5)未定义的处理方式
class A
{
public:
A::A(int i):m_data(i){}
void SetValue(int i)
{ int *p = (int*)&m_data; *p = i } // 这里处理
private:
int m_data;
};
注意:这里虽然说可以修改,但结果是未定义的,避免使用!
3.修饰类对象
const A a; // 类对象a 只能调用const 成员函数,否则编译器报错。
4.修饰类成员函数的返回值
const A operator+(const A &) const; // 前一个const 用来修饰重载函数operator+的返回值,可防止返回值作为左值进行赋值操作。
例如:
A a;
A b;
A c;
a + b = c; // errro: 如果在没有const 修饰返回值的情况下,编译器不会报错。
七、使用const的一些建议

1.要大胆的使用const,这将给你带来无尽的益处,但前提是你必须搞清楚原委;
2.要避免最一般的赋值操作错误,如将const变量赋值,具体可见思考题;
3.在参数中使用const应该使用引用或指针,而不是一般的对象实例,原因同上;
4.const在成员函数中的三种用法(参数、返回值、函数)要很好的使用;
5.不要轻易的将函数的返回值类型定为const;
6.除了重载操作符外一般不要将返回值类型定为对某个对象的const引用;
八、cons有什么主要的作用?
1.可以定义const常量,具有不可变性。
例如:
const int Max=100;
int Array[Max];


2.便于进行类型检查,使编译器对处理内容有更多了解,消除了一些隐患。
例如:
void f(const int i) { .........}
编译器就会知道i是一个常量,不允许修改;


3.可以避免意义模糊的数字出现,同样可以很方便地进行参数的调整和修改。
同宏定义一样,可以做到不变则已,一变都变!如(1)中,如果想修改Max的内容,只需要:const int Max=you want;即可!


4.可以保护被修饰的东西,防止意外的修改,增强程序的健壮性。
还是上面的例子,如果在函数体内修改了i,编译器就会报错;
例如:
void f(const int i) { i=10;//error! }


5.为函数重载提供了一个参考。
class A
{
......
void f(int i) {......} file://一个函数
void f(int i) const {......} file://上一个函数的重载
......
};


6.可以节省空间,避免不必要的内存分配。
例如:
#define PI 3.14159 file://常量宏
const doulbe Pi=3.14159; file://此时并未将Pi放入ROM中
......
double i=Pi; file://此时为Pi分配内存,以后不再分配!
double I=PI; file://编译期间进行宏替换,分配内存
double j=Pi; file://没有内存分配
double J=PI; file://再进行宏替换,又一次分配内存!
const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。


7.提高了效率。
编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。
{
size = sz; // error:试图在构造函数体内对const成员变量进行初始化
}