C++ Using inheritance to tweak an algorithm

穿精又带淫゛_ 提交于 2021-02-10 07:25:09

问题


Since Dijkstra's algorithm and Prim's algorithm are so similar, I'd like to make a base algorithm class (I'll call it "Greedy" or something) and then I want to inherit from Greedy and tweak the algorithm based on the class.

I think it boils down to this. I'd like to reuse a large portion of an algorithm but tweak an operation or two.

class BaseAlg
{
public:
    BaseAlg(std::vector<int> data)  //constructor sums a vector and stores result
    {
        int accum = 0;
        for (unsigned int i = 0; i < data.size(); ++i)
            accum += data[i];
        result = accum;
    }

protected:
    int result;
};

class Alg1  //A second, similar algorithm
{
public:
    Alg1(std::vector<int> data)
    {
        //I want to reuse BaseAlg except use *= instead of +=; 
    }
};

So one way to do this is to only have one class (BaseAlg) and to add a "Selector" value to the class's constructor. I would switch on that selector value and execute += or *= in different cases. I feel like there should be a way to implement this reuse with inheritance because there is an "is a" relationship between Greedy and Prim and Greedy and Dijkstra. But I can't quite figure it out. Any thoughts?


回答1:


You should use templates for this kind of "reuse but nor really inheritance".

For instance, in your case, basically it boils down to this:

template<class Op, class Iter, class T> T reduce(const Op & op, Iter begin, Iter end, T init = T()) {
    T accum = init;
    for(Iter i = begin; i != end; ++i)
        accum = Op(accum, *i);
    return accum;
}

You could then use it like this:

std::vector<int> data; // fill data
int sum = reduce(add<int>, data.begin(), data.end());
int prod = reduce(mul<int>, data.begin(), data.end(), 1);

where you'd need to define add and mult like this:

template<class T> T add(T a, T b) { return a + b; }
template<class T> T mult(T a, T b) { return a * b; }

Now, this was all for illustrative purpose, as Jerry Coffin pointed out, with the STL you can simply do:

#include <functional>
#include <numeric>
int sum = std::accumulate(data.begin(), data.end(), 0, std::plus<int>);



回答2:


Please have a look at Template Method pattern




回答3:


Although I'd go with Antoin's solution, the inheritance might also work (but it looks crappy):

class BaseAlg {
public:
   BaseAlg () : result (0) {}
   virtual ~BaseAlg () {}

   int Accumulate (std::vector<int>& data) {
      for (unsigned int i = 0; i < data.size(); ++i)
         result = func (accum, data[i]);
      return result;
   }
protected:
   virtual int func (int a, int b) = 0;
private:
   int result;
};

class AlgMult : public BaseAlg {
private:
   virtual int func (int a, int b) {
      return a*b;
   }
};

class AlgSum : public BaseAlg {
private:
   virtual int func (int a, int b) {
      return a+b;
   }
};


来源:https://stackoverflow.com/questions/20127392/c-using-inheritance-to-tweak-an-algorithm

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!