让我们说我有一个类:

class NumberCollection
{
public:
    typedef std::set<int> SetType;
    typedef SetType::iterator iterator;
    void insert(int n);

    iterator begin();
    iterator end();
    size_t size() const;

    iterator difficultBegin();
    iterator difficultEnd();
    size_t difficultSize() const;    

private:
    SetType easySet_, difficultSet_;
}

其中insert()增加easySet_的元件。 difficultSet_成员的变化取决于easySet_的成员。

我遇到的问题是,多个插入意味着difficultSet_不断重新计算。所以我想懒洋洋地计算difficultSet_(即difficultBegin()difficultEnd(),或difficultSize()被称为只有当)。问题是,然后我实际上是使difficultSet_mutable否则difficultSize()不能操作就可以了。

所以,现在我的类的声明看起来像

class NumberCollection
{
public:
    typedef std::set<int> SetType;
    typedef SetType::iterator iterator;
    void insert(int n);

    iterator begin();
    iterator end();
    size_t size() const;

    iterator difficultBegin();
    iterator difficultEnd();
    size_t difficultSize() const;    

private:
    SetType easySet_; 
    mutable SetType difficultSet_;
    mutable bool upToDate_;
}

我觉得这是不好的设计,但。有没有更好的办法?

有帮助吗?

解决方案

这是完全做到这一点的方式。常量可以表示二进制的常量,或者它可能意味着概念常量。使用可变意味着你正在做后期,这是很好的。

其他提示

要帮助理解为什么要使用可变的,我们可以探索其他选项。

可以使用解决同样的问题的的const_cast

size_t NumberCollection::difficultSize() const
{
     if(!upToDate_)
     {
          NumberCollection& nonConst = const_cast<NumberCollection&>(*this);
          nonConst.difficultSet_ = PerformExpensiveCalculationFunction();
          nonConst.upToDate_ = true;
     }
     // etc....
}

已经提出了这样的解决方案,我会说,这是不如使用可变。如果一个成员被标记为的可变的,则简单地通过看头我可以收集你如何处理它。如果你使用的的const_cast 我没有得到这个信息。

但随后有人可能采取辩论的另一面,并说,这是最好不要在标题中暴露的实现细节。

这基本上是C ++具有可变结构的原因。艾伦·迪斯的咆哮了解的可变滥用显示了种情况中,可变不应当被使用。

在这种情况下,difficultSize()不改变什么NumberCollection表示 - 它适合于标记为const。它是如何以往任何时候都需要改变的时候了内部,这就是为什么你需要标记difficultSet_和upToDate_为可变的。

您的解决方案是在C ++ 98细。请注意,在C ++ 11,你应该考虑到访问您的可变数据同步。否则,在你的类使用STL,它假定所有的const成员函数是线程安全的,你可能会遇到问题。

有关进一步详情,请参阅是否意味着常量线程安全在C ++ 11?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top