C++ Const总结

一、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的...


你可能感兴趣的:(C++ Const总结)