const int i=10;
int array[i]; // 在C++中合法
const int arr[]={1,3,5};
int arr2[arr[2]]; // 在C++中不合法
struct s{int i;intj;};
const s[]={{1,2},{4,5}};
int arr3[s[1].j]; // 在C++中不合法
备注:C编译器不能把const看成一个编译期间的常量,所以上面情况在C中都不合法。对于类里的常数表达式来说,const就像它在C中一样没有作用。对于类,可以使用enum是不会占用对象中的存储空间的,枚举常量在编译时被全部求值。可以把一个非const对象的地址赋给一个const指针,因为也许有时不想改变某些可以改变的东西。然而,不能把一个const对象的地址赋给一个非const指针,因为这样做可能通过被赋值指针改变这个const指针。当然,总能用类型转换强制进行这样的赋值。
int d=1;
const int e=2;
int *u=&d; // 合法
int *v=&e; // 不合法
int *w=(int*)&e; //合法,但是不好。
如果不让对象的返回值作为一个左值使用,当返回一个对象的值时,应该使用const。但是返回一个内部数据类型的值时,const没有意义的原因是:编译器已经不让它成为一个左值。仅当返回用户定义的类型对象的值时,才会出现上述问题。在类里面,如果声明一个成员函数为const函数,则等于告诉编译器可以为一个const对象调用这个函数。一个没有被特别声明为const的成员函数被看成是将要修改对象中数据成员的函数,而且编译器不允许为一个const对象调用这个函数。
按位const意思是对象中的每个位是固定的,所以对象的每个位映像从不改变。按成员const意思是,虽然整个对象从概念上讲是不变的,但是某个成员可能有变化。
任何不修改成员数据的函数应该声明为const函数,即把const标识符放在参数表后(声明和定义时都要)。在const成员函数里改变数据成员的两种方法:(a)“强制转换const”,取this(这个关键字产生当前对象的地址)并把它强制转换成指向当前类型对象的指针。 (b)在类声明里使用关键字mutable,以指定一个特定的数据成员可以在一个const对象里被改变。
class Y{
int i,j;
mutable int k; //-----
public:
Y(){ i=j=k=0;}
void f() const;
};
void Y::f() const { //------
// ! i++; // 错误
((Y*)this)->j++; // 方式(a)
k++; // 方式(b)
}
int main()
{
const Y yy;
yy.f(); // 改变了
}