【问题标题】:Passing a collection of partially editable objects to an algorithm将部分可编辑对象的集合传递给算法
【发布时间】:2015-08-30 18:55:23
【问题描述】:

我用一个简单的例子简化了我的问题:想象我管理一个元素集合std::vector<Element>,每个元素都有几个成员:

struct Element
{
  public:
    double foo;
    double bar;
};

然后,我想定义一个抽象类BarEvaluator,用于根据a 的值计算b 的值的算法。我的第一个想法是:

class BarEvaluator
{
  public:
    virtual void evaluate(std::vector<Element>& elements) const = 0;
};

据此,我可以实现几种算法,例如,将bar 值计算为foo 值的平方的算法:

class SqrBarEvaluator
{
  public:
    virtual void evaluate(std::vector<Element>& elements) const
    {
      for(unsigned long int i = 0; i < elements.size(); ++i)
        elements[i].bar = elements[i].foo * elements[i].foo;
    }
};

这运作良好。但我认为这不是一个非常好的架构,因为我的算法也能够修改foo。我不想那样。

然后我希望能够使用一种“过滤器”将我的集合提供给算法,该“过滤器”允许仅修改每个元素中的 bar 变量而不是 foo 变量。 C++98 可以吗?我不知道该怎么做。

备注 1: 我不想在 Element 中使用 publicprivate。你可以想象我也想创建算法FooEvaluatorbar值计算foo值,写访问foo而不是bar

备注2:该算法可以要求所有的集合来计算每个值。

【问题讨论】:

  • 这不正是protected、private和getter/setter方法的概念存在的原因吗?
  • 不,我不想限制每个人访问Element,只是为了算法。
  • 你为什么使用 C++98?
  • 在一般情况下,正如您所描述的那样,// DO NOT MODIFY .foo OR A CADUCHON WILL COME AFTER YOU 确实是最好的解决方案。 C++ 会提供涉及另一层抽象的各种解决方案,但我建议不要在这种情况下使用它们。
  • :-) 当然,文档也可以是一种解决方案。我虽然关于集合的代理,但它看起来很丑陋并且实现起来非常复杂。

标签: c++ arguments constants abstract-class


【解决方案1】:

也许你应该把循环拉出界面。

class BarEvaluator
{
  public:
    virtual double evaluate(const Element& element) const = 0;
};

class SqrBarEvaluator
{
  public:
    virtual double evaluate(const Element& element) const
    {
      return element.foo * element.foo;
    }
};

那你这样称呼它:

std::vector<Element> elements;
...
for (std::vector<Element>::iterator it = elements.begin(); it != elements.end(); ++it) {
    it->bar = barEvaluator.evaluate(*it);
}

【讨论】:

  • 其实算法可以要求所有集合计算bar的值。示例:一种计算与其他值均值的距离的算法。我真正的问题就是这种情况。
  • @Caduchon:这是一个两步过程。 1)迭代计算平均值。 2)迭代并计算距离。两者都可以用算法解决。
  • 在这种情况下,算法类不能是const。
  • 你的意思是实例?为什么这是个问题?
【解决方案2】:

您可以使用包装器:

class BarElementWrapper
{
public:
    BarElementWrapper(Element& e) : elem(e) { }
    double getFoo() { return elem.foo; }
    void setBar(double b) { elem.bar = b; }

private:
    Element& elem;
}

然后你的算法会收到一个 BarElementWrapper 的集合。

【讨论】:

    猜你喜欢
    • 2014-11-04
    • 1970-01-01
    • 2012-08-28
    • 2013-11-30
    • 1970-01-01
    • 2018-06-13
    • 2015-08-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多