Const成员函数

时间:2014-05-09 23:06:16

标签: c++ const

const成员函数保证成员函数不能更改任何成员变量,除非它们被标记为可变。

那是说它什么都不保证?

这是一个真实的例子。我有一个课程EventHandlerEventDispatcher

class EventHandler
{
public:
   void registerHandler(EventHandler* handler) const   // Should this be a const?
   {
      EventDispatcher::registerHandler(handler);
   }
};

EventDispatcher   // Singleton Class
{
public:
   void registerHandler(EventHandler* handler)
   {
      mListeners.push_back(handler);
   }

private:
   std::vector<EventHandler*> mListeners;
};

EventDispatcher的{​​{1}}应该是const吗?它不会更改其成员变量,但会改变全局状态。

2 个答案:

答案 0 :(得分:3)

正确,它不保证除了对象本身之外的任何其他状态。我会说没有特别要求它不会修改全局状态。 [如果你把它带到极端,任何函数调用都会修改处理器的当前状态 - 即使它只是将返回地址存储在堆栈[1]]。

但更合理的是const成员函数如下:

 class myclass
 {
 private:
    std::vector<int> v;
 public:
    std::vector<int> getV() const { return v; }
 };

这将创建向量v的副本 - 它又分配内存(从而改变全局状态)。将对象提供给输出流的输出函数也是类似的。

如果一个成员函数修改某个全局状态(以一种不明显的方式),那么它可能应该在函数的描述中明确(文档有时是有用的)。

[1]当然,C ++和C标准没有声明处理器必须有堆栈,返回地址等 - 编译器可以内联所有代码,而不是进行任何“调用”,或者用魔法来“记住”回到哪里 - 只要魔法真的有效,依靠它就可以了。

根据您编辑过的问题进行修改:

这是在任何一个方向上并不完全明显的那些之一,你会期望registerHanlder做一些像“将处理程序对象存储在某个地方”的东西。但由于它不会修改对象本身,因此可能有助于解释它正在更新调度程序类。当然,如果它实际上没有更新类本身,或者使用类中的任何东西,你可能应该使它static而不是const - 这样很明显它实际上并没有修改对象本身。

除此之外:在编写时,您的代码将无效,因为EventDispatcher::registerHandler不是静态成员,而您的EventHandler::registerHandler并未引用EventDispatcher的实例。您可能必须将EventDispatcher的实例作为全局变量,或使EventDispatcher::registerHandler成为静态函数,并使mListeners成为静态成员。或者其他类似的东西。

答案 1 :(得分:2)

方法声明背后的const关键字保证什么?

保证是合同提醒,而不是“物理”记忆障碍。

因此,如果正确实现const关键字,编译器将能够帮助检测可能的错误。

但是,没有C / C ++编译器会停止您直接修改成员状态;既不是通过字段也不是通过将对象引用转换为指针并修改底层内存。

我的const方法是否允许更改(本地/全局)状态?

不允许const方法更改系统的外部行为,但const方法更改内部状态完全可以接受即可。

换句话说,在随机调用所有const方法几次后,系统仍应提供与最初相同的行为。

另一方面,如果const方法感觉缓存耗时的计算并将其重新用于下一次调用,则应该允许它。记录统计信息的记录器类也是如此,但不会改变系统的行为。