对象数组的特定成员的总和

时间:2013-05-15 09:21:37

标签: c++ sum member

这是我在这里的第一个问题,所以希望它是一个很好的问题(我已经找到了答案,但还没有找到答案)。

我有一个用C ++编写的基于事件的疾病模型,我正在尝试将其转换为OOP(部分用于我自己的学习经历)。基本类(Herd)存储易感,感染和抗性动物的数量,以及可能发生的事件的发生率。

class Herd {  
    private: 
        int S,I,R,N;  
        float birth, death, infection, recovery, movement;  
    public:  
        void calc_birth(void) { birth = r*N*(1.0-N/c); }  
        void calc_infection(void) { infection = N>0 ? beta*S*I/N : 0.0; }  
        // etc.
};  

然后我有一个vector个牛群来跟踪。在整个模型中,我需要计算所有牛群中每个成员的总和,在事件改变了牛群中个体的数量或类别后(这种情况发生了很多)。我已经有4个类别和5个事件,这个模型很容易扩展,需要更多。

在我原来的程序代码中,我只是为每个成员创建了一个单独的向量,并且很容易创建一个sum()函数来计算结果,但我看不到如何使用class没有为每个成员写一个单独的sum函数(这是可能的,但我怀疑这是一个特别好的方法)。我可以创建一个静态成员(例如sum_S)来跟踪总数,并在每次事件发生时更新它但这可能不适合所有成员,我不确定总数是否可能不会慢慢徘徊在费率方面远离真正的价值。

有没有办法编写单个sum()函数,它将我想要的成员作为参数,并返回所有牛群中该特定成员的总和?

谢谢!

3 个答案:

答案 0 :(得分:4)

标准库标题numeric包含函数accumulate。它并不完全符合您的要求,但很容易适应:

#include <numeric>
#include <vector>
#include <iostream>

struct Foo {
  int member;
};


int main()
{
  std::vector<Foo> v = { {1}, {2}, {3} };

  int sum 
    = std::accumulate(begin(v), end(v), 0,
                      // lambda that sums up
                      [](const int& x, const Foo& y)
                      {return x + y.member;});
  std::cout << sum << std::endl;

  return 0;
}

代码使用initializer_lists和lambdas。如果您的编译器不支持这些,请使用相应的C ++ 03代码(push_back和仿函数)。

答案 1 :(得分:1)

当然,使用指向成员的指针。

float sum_for_member( std::vector< Herd > const &herds, float Herd::*member ) {
    float acc = 0;
    for ( std:vector< Herd >::const_iterator it = herds.begin();
                                             it != herds.end(); ++ it ) {
        acc += (*it).*member;
    }
    return acc;
}

称呼它:

float total_recovery = sum_for_member( my_herds, & Herd::recovery );

如果您想使用成员函数getRecovery,参数声明将变为float (Herd::*member)(),求和变为acc += ((*it).*member)()


如果您不害怕从OO进一步深入到通用C ++风格,您可以使用功能模板让标准库负责循环:

template< float Herd::*member >
float plus( float lhs, Herd const &rhs )
    { return lhs + rhs.*member; }

vector< Herd > h;
std::accumulate( h.begin(), h.end(), 0., plus< & Herd::recovery > );

答案 2 :(得分:0)

所以这就是我最终的结果(在一个名为State的类中,它保存模拟状态,包括vector<Herd>):

Class State {
    ...
    template <typename T>
        T sum(T (Herd::*getter)()) {
        T acc = (T) 0.0;
        for (int i=0; i<size; ++i) {
            acc += (herds[i].*getter)();
            }
        return acc;
    ...
}

这适用于个体数量(int s)和事件率(float s),并使用指向成员函数的指针来保留这些值private。如何在代码中调用它的示例是:

cout << "total # of S = " << state.sum(&Herd::getS)
    "total # of I = " << state.sum(&Herd::getI)
    "total birth rate = " << state.sum(&Herd::get_birth)
    "total infection rate = " << state.sum(&Herd::get_infection)

非常感谢你的帮助,特别是对Potatoswatter的帮助。这比我以前繁琐的样板代码要好得多!