我想问一下mutable的使用是否合适:
#include <iostream>
class Base
{
protected:
int x;
public:
virtual void NoMod() const
{
std::cout << x << std::endl;
}
void Draw() const
{
this->NoMod();
}
};
class Derive : public Base
{
private:
mutable int y;
public:
void NoMod() const
{
y = 5;
}
};
int main()
{
Derive derive;
// Test virtual with derive
derive.Draw();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Base类是第三方库.我正在扩展它以提供我自己的NoMod().库原始NoMod()声明为const.
我的NoMod()与Base的不同之处在于它需要修改自己的成员变量.
因此,对于我自己的NoMod()来编译并在调用Draw()时调用,我必须这样做
1)实现Derive :: NoMod()作为const
2)使我的int y可变.
这是我能做的最好的吗?
很难说,因为你没有给出任何y关于它的使用或如何使用的背景.
通常,mutable仅在更改可变变量时才适用于不更改对象的实际"值".例如,当我为C风格的字符串编写包装器时,我需要使内部mLength变量可变,以便我可以缓存长度,即使它所请求的东西是一个const对象.它没有改变长度或字符串,并且在类本身之外是不可见的,所以使它mutable没问题.
正如"头脑极客"所描述的,您问题的答案取决于您的数据成员的使用方式.
我在一个类中区分了两种类型的数据成员.
我使用通用术语"属性"来指代作为对象的逻辑状态或"值"的数据成员.通常,属性很少被声明为可变的.
我创造了原始主义'贡献',它表示数据成员只是"工作内存/存储",并且有点与对象的状态脱节.Contributes与对象的用户没有上下文相关性,它们只存在于类中,有助于对象的维护和高效操作.Contributes通常在类中声明为可变的,并且始终是私有的或受保护的.
例如,假设您的对象是链接列表,因此您有一个指向列表中第一个项目的指针.我认为这个指针是有贡献的,因为它不代表列表中的数据.即使列表已排序且指针设置为列表中的新第一项,列表对象的用户也可能不关心列表的维护方式.仅列表数据已被修改,并且列表是否已排序与用户的观点相关.即使您有一个booean数据成员'已排序'以快速确定列表是否处于排序状态,这也是一个贡献,因为它是列表结构本身,其中包含排序状态,使用'sorted'变量成员只需有效地记住状态而无需扫描列表.
另一个例子,如果你有一个const方法来搜索列表.假设您知道通常搜索将返回最近搜索过的项目,您可以在类中保留指向此类项目的指针,以便您的方法可以在搜索整个列表之前首先检查最后找到的项目是否与搜索关键字匹配(如果该方法确实需要搜索列表并找到一个项目,则指针将被更新).这个指针我认为是一个贡献因为它只是帮助加快搜索速度.即使搜索更新了指针贡献,该方法也是有效的const,因为容器中的所有项都没有被修改.
因此,属性的数据成员通常不会被声明为可变的,并且有助于对象运行的数据成员通常是可变的.