【问题标题】:How to keep this const-correct without cheating the compiler?如何在不欺骗编译器的情况下保持这个常量正确?
【发布时间】:2011-12-17 13:57:26
【问题描述】:

我有一个这样的 C++ 类:

class Example {

    public:

        int getSomeProperty(int id) const;

    private:

        lazilyLoadSomeData();

}

基本上getSomeProperty() 返回一些已经使用lazilyLoadSomeData() 加载的数据。由于我不想在需要之前加载这些数据,所以我在 getSomeProperty() 中调用此方法

int Example::getSomeProperty(int id) const {
    lazilyLoadSomeData(); // Now the data is loaded
    return loadedData[id];
}

这不起作用,因为 lazilyLoadSomeData() 不是 const。即使它只更改可变数据成员,编译器也不会允许它。我能想到的唯一两个解决方案是:

  • 在类构造函数中加载数据,但我不想这样做,因为延迟加载所有内容会使应用程序更快。

  • lazilyLoadSomeData() 设为常量。它会起作用,因为它只更改可变成员,但它似乎并不正确,因为从名称来看,该方法显然正在加载某些内容并且显然正在进行一些更改。

关于什么是处理这个问题的正确方法有什么建议,而不必欺骗编译器(或完全放弃 const 正确性)?

【问题讨论】:

  • ¤ 这就是 mutable 关键字的用途。更倾向于“作弊”方向的另一种选择是保留指向数据的指针。我提到这一点是为了明确识别反模式并避免它;对惰性数据使用mutable。干杯&hth.,

标签: c++ const-correctness


【解决方案1】:

您可以创建一个您声明mutable 并封装延迟加载策略的代理成员对象。该代理本身可以从您的 const 函数中使用。作为奖励,您最终可能会得到一些可重用的代码。

【讨论】:

  • 除了...从语义上讲,您只是做完全相同的事情,因此有人可能会说这是同一个问题。老实说,问题是“愚蠢”是某种方式,因为mutable 是关于作弊,以一种受控的方式。
【解决方案2】:

我会将调用转发到一个代理对象,它是此类的 mutable 成员,如下所示:

class Example {

    public:

        int getSomeProperty(int id) const
        {
            m_proxy.LazyLoad();
            return m_proxy.getProperty(id);
        }

    private:

        struct LazilyLoadableData
        {
             int GetProperty(int id) const;
             void LazyLoad();
       };

     mutable LazilyLoadableData m_proxy;
};

【讨论】:

  • 当您不使用“pImpl”时确实如此。但如果你这样做,就不需要可变的。您可以只修改 pImpl 指向的内容,因为只有 pImpl 本身是 const..
【解决方案3】:

将 lazilyLoadSomeData() 设为常量。它会起作用,因为它只更改可变成员,但它似乎并不正确,因为从名称来看,该方法显然正在加载某些内容并且显然正在进行一些更改。

不,它没有做出一些改变,至少从调用 getSomeProperty 的人的角度来看是这样。如果你做对了,所有的变化都是纯粹的内部变化,从外部看不到。这是我会选择的解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-21
    • 2019-02-15
    • 2020-09-05
    • 1970-01-01
    相关资源
    最近更新 更多