- 论坛徽章:
- 0
|
回复 #1 jchc 的帖子
map<string,string> getAll(){return mp;} //3
但我把方法3前增加了const ,也一样报这个错。请大家能否解释下吗?
map<string,string> getAll() const {return mp;} //3
这才是表示一个成员函数是const的,意思是调用这个成员函数不会改变该对象。
http://blog.chinaunix.net/u/23408/showart.php?id=191168
关键字 const 和 mutable
const 修饰常量与形式参数
const 可以而且应当尽量用来修饰常量(或函数的形式参数)告诉编译器该数据不会改变。将常量用“const”标明的最大好处是可以在编译器就发现不期望的修改。而且也有助于代码优化——不论是编译器还是程序员自己进行优化。比如说“copy on write”。
const 对传值调用也有意义
void f(const int i){
++i; //error: increment of read-only parameter `i'
}
基本类型的常量可以定义在头文件中
const常量默认为“internal linkage”,所以const常量定义在头文件中是合法的。但是这么做会导致每个包含该头文件的编译模块拥有一份该常量的拷贝。
一般来说,基本类型的常量(尤其是整型)可以定义在头文件中,好处是:
* 可以确保各个编译模块中的常量保持一致。
* 可以用整型常量来定义静态数组。
静态数组长度一般用整型字面常量或者相应的宏表示(T array[LEN])字面常量的缺点显而易见。宏应用在此处虽然没什么大问题但毕竟还是存在一定缺点。用整型常量相对来讲是最好的选择。可是由于定义静态数组时数组长度必须已知,所以整型常量的值必须在静态数组定义时可见。如果整型常量定义在另一个.cc文件中,就无法用该常量来定义数组。反之,如果该常量定义在头文件中且该头文件又被包含则可。
错误:
// a.h:
extern const int ARRAY_LEN;
// b.cc:
#include "a.h"
const int ARRAY_LEN = 10;
// c.cc:
#include "a.h"
int a[ARRAY_LEN]; // error
正确:
// a.h
const int ARRAY_LEN = 10;
// c.cc
#include "a.h"
int a[ARRAY_LEN]; // ok
但是复合类型常量别定义在头文件中
例子(跳过?)
test.h
#include <iostream>
#ifndef TEST_H
#define TEST_H 1
using namespace std;
class CA
{
public:
static int i;
CA() { ++ CA::i;}
};
const CA a;
#endif // TEST_H
test1.cc
#include "test.h"
void f()
{
cout << a.i << endl;
}
test.cc
#include "test.h"
void f();
int CA::i = 0;
int main(int argc, char argv[]){
f();
cout <<a.i <<endl;
return 0;
}
compile & result (cygwin)
g++ test.cc test1.cc
result:
2
2
const 修饰成员函数
const 还可以用来修饰成员函数以表明它不会破坏对象的逻辑不变性。
物理不变与逻辑不变
逻辑不变(Logical Constness)指的是对象的呈现给用户的状态不变,但它的成员变量是否变化则不一定。与逻辑不变相对应的还有物理不变(Physical Constness)。所谓物理不变指的是对象的任何成员变量都不作任何改动。有时两者是一致的,但有很多时候两者并不一致。例如:假设有如下多线程环境下的set类,它的成员函数getData()获取指定键值的元素。
例子: MtSet
template <typename _K_,
typename _Compare_=
std::less<_K_> >
class MtSet{
public:
_K_ getData(const key_type& key) const{
MutexLock lock(_mutex_);
return (_set_.find(key));
}
public:
std::set<key_type> _set_;
mutable Mutex _mutex_;
// ...
};
显然,从逻辑上说getData()不修改调用它的对象,即不破坏对象的逻辑不变性;但是为了线程同步,getData()必然要先锁住互斥锁(_mutex_),也就必然破坏对象的物理不变性。
关键字 mutable
上一节讲到const成员函数应当保持对象逻辑上不变。但是一个成员函数被定义成 const成员后,编译器禁止它修改对象的任何属性。如果成员函数确实需要在不破坏对象逻辑不变性的前提下修改某一属性就需要借助关键字 mutable 了。
关键字 mutable 表示被修饰者在任何情况下都不为常量。上例中MtSet把_mutex_定义成mutable变量。不论MtSet的对象是否为常量,_mutex_都是一个“变”量。
[ 本帖最后由 lgfang 于 2008-9-25 13:40 编辑 ] |
|