问题
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