0

我有一个“项目”,其数据可以用 3 种方式表示。我可以以运行时成本从一种表示转换为任何其他表示。完成转换后,我想保留新的表示形式。数据的任何表示都可以转换为其他任何表示,而无需“修改”核心数据。由于运行时成本,我想要一个包含 3 种数据表示的类。在任何时候,其中的 1 到 3 个都是有效的。

这样做的真正意义在于它还具有访问方法,用户可以在其中请求某些东西。这可以从 1 个或更多的表示中得到。例如,您可以从表示 1 中获取“范围”,从表示 2 或 3 中获取“体积”。

我的解决方案是创建具有 3 种表示形式的类作为成员数据(以及一种知道它们是否有效的方法)。然后我创建了一个 getRange() 方法,该方法在内部知道它需要哪种表示并在必要时创建它。除了 get 方法不能是 const 之外,这可以正常工作并解决我的所有问题。

所以这个解决方案的真正问题是,即使是这个类的“常量”实例也不是真正的 const,因为它在内部可能会创建其他表示。但是它确实是“恒定的”,因为更改表示不会修改核心数据。

是否有可能对此类有所帮助的 C++ 设计模式?有什么建议么?

4

2 回答 2

3

我的解决方案是创建具有 3 种表示形式的类作为成员数据(以及一种知道它们是否有效的方法)。然后我创建了一个 getRange() 方法,该方法在内部知道它需要哪种表示并在必要时创建它。这工作正常并解决了我的所有问题,除了 get 方法不能是 const

这正是mutable指定类型的目的!为了能够在仍有const方法的同时更新内部表示,使表示属性mutable

struct A {

    int get_range() const {
        if (!_repr2.is_valid()) {
            _repr2 = Repr2(_repr1); // I am in a const method, but still
                                    // I can update a mutable attribute
        }
        return _repr2.get_range();
    }    

private:
    mutable Repr1 _repr1;
    mutable Repr2 _repr2;
};

是一个完整的示例,其中包含两个std::unique_ptr用于存储表示的表示,因此您可以轻松检查一个是否被实例化。

于 2016-04-29T15:08:07.457 回答
1

根据霍尔特的回答,可变是这里需要的主要内容。您还可以从boost::optional<ReprX>存储表示中受益。这有助于解决问题的“知道它们是否有效的方法”:

struct A {

    int get_range() const {
        if (!_repr2) {
            _repr2 = Repr2(*_repr1); 
        }
        return _repr2->get_range();
    }    

private:
    mutable boost::optional<Repr1> _repr1;
    mutable boost::optional<Repr2> _repr2;
};
于 2016-04-29T15:14:40.050 回答