(防止脑抽还是记一笔)成员函数:全称是 类成员函数,声明在类里面,定义可以在类里也可以在类外部,外部的话需要用 int 类名::函数名(int x){...}定义
问题描述
class TextBlock{
public:
...
const char& operator[] (std::size_t pos) const {
return text[pos]; // const 成员函数
}
char& operator[] (std::size_t pos) {
return text[pos]; // non-const 成员函数
}
private:
std::string text;
};
// 对比
TextBlock text1("111");
const TextBlock text2("111");
std::cout << text1[0]; // ok
std::cout << text2[0]; // ok
test1[0] = '0'; // ok
test2[0] = '0'; // err
// 贴近实际的例子 调用const
void print(const TextBlock& text3) {
std::cout << text3[0];
}
解读:
对比中最后一行text2的err:它的返回类型是 const char& , 不可以赋值
char& operator[] (std::size_t pos):它的返回类型是 reference to char , 不是char
引申的技巧-----避免代码重复
【如何避免上述const 和non-const函数的代码重复问题】
class TextBlock{
public:
...
const char& operator[] (std::size_t pos) const {
... // const 成员函数 包含很多内容
return text[pos];
}
char& operator[] (std::size_t pos) { // non-const 成员函数 只有一行 避免重复
return const_cast<char&>(static_cast<const TextBlock&>(*this)[pos]);
}
private:
std::string text;
};
注意:只能non-const调用const , 绝不能反过来
解读:用*this 将TextBlock& 转型(casting)为 const TextBlock&,再从 const operator[]的返回值中第二次转型,通过const_cast移除const。哇哦。。漂亮
好像没什么用的备注点
不想看可以只看这一行:第一行 const 成员函数里的两个const都不能省
对【const成员函数意味着什么】的理解
——分为两类
第一类:bitwise constness, 指const成员函数不能更改任何non-static成员变量,这通过编译器查询变量赋值动作来判断。
然而......有个问题:
对于第一行 const 成员函数里的两个const,后面那个用于说明operator[]是const,这里省略第一个
class TextBlock{
public:
...
char& operator[] (std::size_t pos) const {
return text[pos]; // const 成员函数
}
private:
char* text;
};
// 对比
const TextBlock text4("111");
char* p = &text4[0];
*p = '1';
在这里,编译器没有发现对成员变量text4的赋值,但实际上,text4的值改变了。所以上述例子不满足bitwise constness的含义,但编译器却认为它是bitwise constness。(好绕)
第二类:logical constness,指const成员函数可以修改某些成员变量,但只有在客户端侦测不出来的时候才行(?)
代码略。总之就是这种情况下编译器通不过了。
因此解决办法:mutable(略)