记住从右往左读,左边的修饰右边的。
char greeting[] = "Hello"; const char* p = greeting;//non-const pointer,const data char* const p = greeting;//const pointer,non-const data
在*之前表示const修饰数据,是底层const,数据不可以修改;
在*之后表示const修饰这个指针,是顶层const,指针的指向不可以修改。
1、const成员函数
两个成员函数如果只是常量性不同,可以被重载。(函数名相同,内容不一样)
在类里面,把一个成员函数声明为const,要将它放在形参表()和{}之间,表示这是个const成员函数,这个成员函数不会更改类对象的内容。
深入部分:
★相同点:
●都是地址的概念;
指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。
★不同点:
●指针是一个实体,而引用仅是个别名;
●引用只能在定义时被初始化一次,之后不可变;指针可变;引用“从一而终”,指针可以“见异思迁”;
●引用没有const,指针有const,const的指针不可变;(具体指没有int& const a这种形式,而const int& a是有 的, 前者指引用本身即别名不可以改变,这是当然的,所以不需要这种形式,后者指引用所指的值不可以改变)
●引用不能为空,指针可以为空;
●“sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身的大小;
●指针和引用的自增(++)运算意义不一样;
●引用是类型安全的,而指针不是 (引用比指针多了类型检查)
如果想在const成员里面修改class的数据成员,可以将数据声明为mutable。
2、在const和non-const成员函数中避免重复
non-const成员函数调用const成员函数,避免代码重复,但是反过来就不行,因为non-const会修改const变量值。
class TextBlock{ public: ... const char& operator[](std::size_t position) const{ ... ... ... return text[position]; } char& operator[](std::size_t position) { return const_cast<char&>( static_cast<const TextBlock&>(*this)[position] ); } //将op[]返回值的const转换为*this加上const调用const op[] };
补充:
命名的强制类型转换:
强制类型转换形式是
cast-name<type>(expression) //其中cast-name是static_cast,dynamic_cast,const_cast,reinterpret_cast //type是要转换的目标类型,expression是要转换的值
static_cast:任何具有明确定义的类型转换,只要不包含底层const,都可以使用static_cast.
double slope = static_cast<double>(j) / i;
const_cast:去掉const性质,只能改变运算对象的底层const,将常量对象转换为非常量对象的行为。,但是如果对象是一个常量,const_cast之后执行写操作就会产生未定义的后果。
不能使用const_cast改变表达式的类型,比如将const char*转换为string就是非法的,只能改变const属性。
3、reinterpret_cast(重解释转换)
比如将指向int的指针变为指向char类型的指针。
总结:
- 将某些东西声明为const可帮助编译器测出错误用法。const可被施加于任何作用域内的对象、函数参数、函数返回类型、成员函数本体。
- 当const和non-const成员函数有着实质等价的实现时,令non-const版本调用const版本可避免代码重复。