const在面试的时候考得多,特地小结一下。
1,const是修饰符,它表示某个对象是常量,即不能修改,而C++没能彻底抛弃指针这个C留下的遗产而有些尴尬,指针是比较圆滑的家伙,它有双重身份,有时表示它自己,有时表示它所指的对象(所以C++建议我们尽量用引用而不是指针)
const double e;// error
const double pi=3.14;// ok,需要初始化
这样的用法没什么好说的。
2,指针带来的问题
像这样写:
int a,b;
const int *p=&a;
实际上没有定义一个常量指针,而是指向常量对象的指针,这意味着后面可以这样
p=&b;//ok
a,b不是常量而是变量,这是可以的,事实上编译器不管这个,而是管*p和p->这样的运算不能被修改
*p=1;//error
就是说上面那句定义的并不是一个常量,它相当于
int const *p;
实际上是个变量。
而真正的常量指针怎么写?这样
int * const p=&a;//ok
int *const p;// error
它的意思是p不能再改,只能赋值一次,这实际上是什么,是引用。引用和指针有着这样一个巨大的差异。
上面ok的代码,实际上可以写成
int &p=a;
也就是说根本不需要常量指针,因为有引用(?)
3,引用和const
引用有着针指的优点,但是它的身份是确定的,不像指针有双重身份,所以用const修饰没什么问题。
const int &p=a;
它的意思实际上和这样写差不多
int const * const p=&a;
本身一次赋值,所指对象也不能改。这就是喜欢考的那个所谓,一个指向一个常量对象的常量指针。
试一下这么写
int const & const p=&a;
多此一举,在VC上会给出个警告,因为在语义上是重复的。
const 指针: const 这个关键字可以用在: 类型前: 指明类型是常数,即所指向的值是常数,值不可改变。 变量前: 指明变量是常数,即指针本身是常数,指针本身不能改变。 const int *p1; //the int pointed to is constant int * const p2; //p2 is constant, it can't point to anything else. 或者上面两者的结合 const int * const p3; //指针本身和指向的内容都不可以改变。 ■声明成员函数为 const 时,编译器把函数内改变对象实例数据的任何企图都视为错误。 ■如果程序声明指向 const 对象的指针,该指针只能调用 const 函数成员。 下面举例说明: class MyClass { private: int FValue; public: void SetValue(int n) { FValue = n; } //定义 const 成员函数 int GetValue() const { return FValue; } }; void main() { //定义指向 const 对象的指针 const MyClass * pConstMyClass = new MyClass; //pConstMyClass->SetValue(100); //非法,不可以改变内容。 pConstMyClass->GetValue(); } 好神奇哦,其中原因就是 const this 指针。 当程序声明对象为 const 时( 见 main() 中定义的 const MyClass ... 那一行 ), 实际上等于编译器生成要调用的成员函数的 this 指针参数为 const MyClass * this 这种形式, 呵呵,这样 this->FValue = n; 显然非法。所以,指向 const 对象的指针只能调用 const 成员函数。即: this 指针为: const class MyClass //定义为 const 时 class MyClass & //非 const 时 当进行类型转换时, class MyClass & 转成 const class MyClass 是可以的,反过来就不行,因此,普通的对象实例可以操作任何成员函数,而不管成员函数有没有 const。 这里要说明一点的是静态成员变量。还记得吗?以前说过,静态成员变量不属于对象实例,只属于类。也就是说编译器要操作静态成员变量,对于非静态成员函数来说是不能用 this 指针去操作它的,因为静态成员变量不在对象实例区,这样一来,即使非静态成员函数声明为 const,还是可以改变静态成员变量的。像本例中 pConstMyClass 是指向 const 对象实例的,但对象实例区并不包含静态成员变量,也就是说,改变静态成员变量也是合法的。 |