return 0;
}同样的,我们可以将string替换为char*表示,代码如下:
class TextBlock{
public:
...
cosnt& operator[](std::size_t position) const{
return pText[position];
}
private:
char* pText;
};
const TextBlock cctb("hello");
char* pc=&cctb[0];
*pc='J';//cctb现在有了"Jello"这样的内容
观察上面的代码,为什么此时cctb[0]的值就可以改了呢?注意operator[]的第二个const指的是不能修改成员变量的值,在这里成员变量的值是pText,pText有没有指向其他地址呀,没有吧,即成员变量的值没有被改变呀,因此肯定可以修改呀!
如果我们想要在不准备修改成员变量的成员函数中想要修改成员变量呢?有些拗口,请看如下代码:
class CTextBlock{
public:
...
std::size_t length() const;
private:
char* pText;
std::size_t textLength;
bool LengthIsValid;
}
std::size_t CTextBlock::length() const{
if(!lengthIsValid){
textLength=std::strlen(pText);
lengthIsValid=true;
}
return textLength;
}
上面代码有木有错呢,当然有错,在const成员函数中修改成员变量,如果我们想要其变为正确的怎么办呢?答案很简单,就是将想要更改的变量声明为mutable即可。
条例三:
在const和non-const成员函数中避免重复
怎么解决呢?C++给出的建议是在non-const成员函数中调用const成员函数,为什么不能烦着来呢?const版本中调用non-const版本,注意const成员函数承诺不改变其对象的逻辑状态,non-const成员函数并没有这样的承诺,如果const调用non-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]]);
...
}
条例4:顶层const和底层const作为重载函数须知
顶层const不影响传入函数的对象,一个拥有顶层const的形参无法和一个没有拥有顶层const的形参区分开来
Record lookup(Phone);
Record lookup(const Phone);
Record lookUp(Phone*);
Record lookUp(Phone* const);
等由于都是顶层const所以每一组的第一个和第二个都一样,无法区分;
底层const确实可以区分的,如果形参是某种类型的指针或者引用,则通过区分其指向的是常量对象还是非常量对象可以实现函数重载,此时const是底层的。
Record lookup(Account&);//作用与Account引用
Record lookup(const Account&);//作用于常量引用
Record lookup(Account*);//作用于指向Account的指针
Record lookup(const Account*);//作用于指向常量的指针
为了更清楚地理解,我编写了如下的函数:
void record(int &a){
cout <<"hahaha:" <}
void record(const int&a){
cout <}
int a = 10;
const int b = 100;
int &a1 = a;
const int &b1 = b;
record(a1);
record(b1);
可以看看运行结果:
PS:
突然发现自己一直对顶层const和底层const的理解有误,紧急补充一下哈~
顶层const:指针本身是个常量,即const出现在指针右侧;
底层const:指针所指向的对象是个常量,即const出现在指针左侧;