C++开发初级
1094 浏览 5 years, 10 months
6.2 const方法
版权声明: 转载请注明出处 http://www.codingsoho.com/const方法
常量对象是值不能改变的对象。如果使用常量对象、常量对象的引用以及指向常量对象的指针,编译器将不允许调用对象的任何方法,除非这些方法承诺不改变任何数据成员。为了保证方法不改变数据成员,可以用const关键字标记方法本身。下面的SpreadsheetCell类包含了用const标记的不改变任何数据成员的方法:
class SpreadsheetCell
{
public:
double getValue() const;
string getString() const;
};
代码取自 SpreadsheetCellMethods\SpreadsheetCell.h
Const规范是方法原型的一部分,方法的定义必须与其匹配:
double SpreadsheetCell::getValue() const
{
}
string SpreadsheetCell::getString() const
{
return mString;
}
代码取自 SpreadsheetCellMethods\SpreadsheetCell.h
将方法标记为const,就是与客户代码立下了契约,承诺不会在方法内改变对象内部的值。如果将实际上修改了数据成员的方法声明为const,编译器将会报错。不能将静态方法声明为const,因为这是多余的。 静态方法没有类的实例,因此不可能改变内部的值。 const的工作原理是将方法内用到的数据成员都标记为const引用,因此如果试图修改数据成员,编译器会报错。
非const对象可以调用const方法以及非const方法。然而,const对象只能调用const方法,下面是一些示例:
SpreadsheetCell myCell(5);
cout << myCell.getValue() << endl; // OK
myCell.set("6"); // OK
const SpreadsheetCell& anotherCell = myCell;
cout << anotherCell.getValue() << endl; // OK
anotherCell.set("6"); // Compilation Error!
代码取自 SpreadsheetCellMethods\SpreadsheetTest.cpp
应该养成习惯,将不修改对象的所有方法声明为const,这样就可以在程序中引用const对象。注意const对象也会被销毁,它们的析构函数也会被调用,因此不应该将析构函数标记为const。
mutable数据成员
有时您编写的方法“逻辑上”是const,但是碰巧改变了对象的数据成员。这个改动对于用户可见的数据没有任何影响,但是在技术上确实做出了改动,因此编译器不会让您将这个方法声明为const。例如,假定您想要让电子表格应用程序获取数据被读取的频率。
完成这个任务的笨办法是在SpreadsheetCell类中加入一个计数器,计算getValue()以及getString()调用的次数。遗憾的是,这样做使得编译器认为这些方法是非const的,这并非您的本意。解决方法是将计数器变量设置为mutable,从而告诉编译器在const()方法中允许改变这个值。下面是新的SpreadsheetCell类定义:
class SpreadsheetCell
{
protected:
double mValue;
string mString;
mutable int mNumAccesses = 0;
//mutable int mNumAccesses; // Pre-C++11
};
代码取自 SpreadsheetCellMethods\SpreadsheetCell.h
下面是getValue()以及getString()的定义:
double SpreadsheetCell::getValue() const
{
mNumAccesses++;
return mValue;
}
string SpreadsheetCell::getString() const
{
mNumAccesses++;
return mString;
}
代码取自 SpreadsheetCellMethods\SpreadsheetCell.h