一、const_cast
来自MSDN的说明:
一个指向对象或对象成员的指针可以显式地转换为带有不同const、volatile或__unaligned属性的同一类型。对于指针和引用,转换结果引用的是原对象。对指向数据成员的指针,转换结果指向原指针(转换前)指向的对象。通过转換得到的指针、引用及(指向数据成员的)指针来进行写操作可以导致未定义的行为——取决于引用对象的类型。
const_cast会将一个空指针转换为一个目标类型的空指针。
总结:
const_cast只能应用于指针或引用类型。似乎从语义上,const_cast只允许重新解释原对象,而避免产生对象的副本。这很好理解:倘若我们要取消某个对象的const属性,多半是为了更改它。如果const_cast产生副本,便人是物非一场空了。
return const_cast<TestConstReload>(*this).v; //error C2440: 'const_cast' : cannot convert from 'const class xx' to 'class xx',对于内置类型同样如此
return const_cast<TestConstReload&>(*this).v; //OK
return const_cast<TestConstReload*>(this)->v; //OK
二、const重载
对于成员函数,可以有相同参数列表,但函数本身的const属性(非参数或返回值的const属性)不同的重载。例如:
classTestConstReload
{
public:
int& val() const
{
cout<<"const"<<endl;
return const_cast<TestConstReload&>(*this).v;
}
int& val()
{
cout<<"non-const"<<endl;
returnv;
}
private:
intv;
};成员函数具有const重载时,类的const对象将调用类的const版本成员函数,类的非const对象将调用非const版本成员函数。
如果只有const成员函数,类的非const对象也可以调用const成员函数。 ——这个思路来描述很囧。下同。
如果只有非const成员函数,类的const对象…额,不能调用非const成员函数。 ——其实跟上一句的意思是一样的:const对象只能调用它的const成员函数。
总的来说,就是当我们调用一个成员函数时,编译器会先检查函数是否有const重载,如果有,将根据对象的const属性来决定应该调用哪一个函数。如果没有const重载,只此一家,那当然就调用这一个了。这时编译器亦要检查函数是不是没有const属性而调用函数的对象又有const属性,若如此,亦无法通过编译。
三、const属性的继承
这里所说的继承与类层次的继承没有关系,意思是指:当我们定义一个const对象时,对象中的数据成员也将具有const属性(不论成员声明是否有const修饰)。这个很好理解,就好比一个const int,其中4个字符都不可更改一样,const对象中的所有数据也同样不可更改。但我之前没有意识到这一点,所以列在此。
在上面的示例类型声明中,int& val() const 之所以要在最后去掉对象的const属性再返回,就是因为若不如此,则类const对象将无法调用此成员函数。
int& val() const { cout<<"const"<<endl; return const_cast<TestConstReload&>(*this).v; } const TestConstReload obj; obj.val(); //error : cannot convert from ‘const int’ to ‘int'
四、const的编译期优化
网上一篇文章描述了这样一个示例:
int main() { const int a = 1; int *p = const_cast<int*>(&a); *p = 2; cout << “°value a=”± << a << endl; cout << “°value *p=”± << *p << endl; cout << “°address a=”± << &a << endl; cout << “°address p=”± << p << endl; return 0; } //输出 value a=1 value *p=2 address a=0xbfe9efb4 address p=0xbfe9efb4(depends on machine)文中同样有相关解释:即使在内存中某个地方存放了a对象,编译器也有可能在引用此变量的地方真的引用它。如果这个对象很小,并且它是常量,在编译时编译器就已经知道它的值。那编译器完全有可能在生成汇编的时候,用一个与它值相同的立即数来代替内存地址——这可以减少一次内存读取操作。原文在此:慎用const_cast
五、托管C++中没有const成员函数
如果在VC.NET中声明一个托管C++类,那么它的成员函数将不能应用const属性。我没有找到关于这一点的说明,大概是因为MISL方面的原因吧。如果哪位有关于托管C++中const的其它资料,请告诉我。
题外话:
1. 总结很费时,不过有助于理清知识和锻炼写作能力。
2. Live Writer怎么不好用了啊,郁闷。害我直接写HTML。哎,貌似很多大牛都是直接写HTML的...