【发布时间】:2018-02-07 15:03:00
【问题描述】:
据我在这里和那里读到的,应该尽可能使用const。然而,我有一个案件一直困扰着我。
如果成员函数不改变任何成员变量值但在概念上不是const 函数,我是否应该将其标记为const?
例如:
class Engine{
public:
int status;
};
class Car{
public:
void start() const{
engine_->status = 1;
}
private:
std::unique_ptr<Engine> engine_;
};
编译器将接受start() 的常量,因为engine_ 作为指针没有改变。但是,至少在 IMO 看来,在一个名为 Car 的类中名为 start 的函数是一个 const ,这似乎太不现实了!
这个例子只是一个简单的例子。通常,Car 类的一些内部状态应该相应地更新,使const 关键字不可行。不过,这个小例子只是为了说明我的想法。
【问题讨论】:
-
STL 使用调用
const成员函数是线程安全的约定。你的start不是。如果你应该遵循这个约定是有争议的。 -
我记得读过 Scott Myers 讨论他认为的逻辑 const-ness 和物理 const-ness 之间的区别。那是关于引入
mutable成员(例如互斥锁)。他的观点是关于证明可修改成员的合理性,因为对象的逻辑状态保持不变,所以成员函数是合理的 const。我认为类似的推理在这里也适用。逻辑状态发生变化,因此省略 const 可能是合理的。 -
调用者通常期望
const指的是对象的逻辑状态,而不是它的表示。所以最好不要将这种情况标记为 const。相反,不表达逻辑状态的成员变量(例如缓存机制)通常声明为mutable,以允许函数为const,即使确实改变了对象的表示。 -
这里可能值得一提的是最小惊讶原则——在这种情况下,如果你的类的用户会惊讶地发现 start() 方法被标记为 const,那么这很好不标记方法 const 的参数。 en.wikipedia.org/wiki/Principle_of_least_astonishment