基于 const 的重载
基于 const 的重载
为了解决这个问题,我们必须定义两个 display 操作:一个是 const,另一个不是 const。 基于成员函数是否为 const, 可以重载一个成员函数; 同样地,基于一个指针形参是否指向 const,可以重载一个函数。const对象只能使用 const 成员。非 const 对象可以使用任一成员,但非 const 版本是一个更好的匹配。
在此,我们将定义一个名为 do_display 的 private 成员来打印 Screen。每个 display 操作都将调用此函数,然后返回调用自己的那个对象:
class Screen {
public:
// interface member functions
// display overloaded on whether the object is const or not
Screen& display(std::ostream &os)
{ do_display(os); return *this; }
const Screen& display(std::ostream &os) const
{ do_display(os); return *this; }
private:
// single function to do the work of displaying a Screen,
// will be called by the display operations
void do_display(std::ostream &os) const
{ os << contents; }
// as before
};
现在, 当我们将 display 嵌入到一个长表达式中时, 将调用非 const 版本。当我们 display 一个 const 对象时,就调用 const 版本:
Screen myScreen(5,3);
const Screen blank(5, 3);
myScreen.set('#').display(cout); // calls nonconst version
blank.display(cout); // calls const version
可变数据成员
有时(但不是很经常),我们希望类的数据成员(甚至在 const 成员函数内)可以修改。这可以通过将它们声明为 mutable 来实现。
可变数据成员(mutable data member) 永远都不能为 const,甚至当它是const 对象的成员时也如此。因此,const 成员函数可以改变 mutable 成员。要将数据成员声明为可变的,必须将关键字 mutable 放在成员声明之前:
class Screen {
public:
// interface member functions
private:
mutable size_t access_ctr; // may change in a const members
// other data members as before
};
我们给 Screen 添加了一个新的可变数据成员 access_ctr。使用access_ctr 来跟踪调用 Screen 成员函数的频繁程度:
void Screen::do_display(std::ostream& os) const
{
++access_ctr; // keep count of calls to any member function
os << contents;
}
尽管 do_display 是 const,它也可以增加 access_ctr。该成员是可变成员,所以,任意成员函数,包括 const 函数,都可以改变 access_ctr 的值。
用于公共代码的私有实用函数
单独定义一个 do_display的原因:
1. 一般愿望是避免在多个地方编写同样的代码。
2. display 操作预期会随着类的演变而变得更复杂。当所涉及的动作变得更复杂时,只在一处而不是两处编写这些动作有更显著的意义。
3. 很可能我们会希望在开发时给 do_display 增加调试信息,这些调试信息将会在代码的最终成品版本中去掉。如果只需要改变一个 do_display 的定义来增加或删除调试代码, 这样做将更容易。
4. 这个额外的函数调用不需要涉及任何开销。我们使 do_display成为内联的,所以调用 do_display 与将代码直接放入 display操作的运行时性能应该是相同的。
实际上, 设计良好的 C++ 程序经常具有许多像 do_display 这样的小函数,它们被调用来完成一些其他函数的“实际”工作。

浙公网安备 33010602011771号