在C ++中,我必须实现几种算法,它们代表了计算同一事物的不同方法。
我考虑使用接口来表示不同的算法。
class AlgorithmInterface
{
public:
virtual double ComputeSomething(void* parameter) = 0;
}
class AlgorithmImplementation1: public AlgorithmInterface
{
public:
virtual double ComputeSomething(void* parameter) { /* implementation */}
}
class AlgorithmImplementation2: public AlgorithmInterface
{
public:
virtual double ComputeSomething(void* parameter) { /* implementation */}
}
然而,每个参数(前一个例子中的void *)都不同,我如何一般地表示它们?
我在示例中使用了void *,因为我不知道如何表示这个。请告诉我应该怎么做:我应该为参数创建等效继承并转换它们吗? (这对我来说似乎很难看)
答案 0 :(得分:9)
您可以在构造函数中传递参数 另外,将虚拟成员设为私有,并使对象成为仿函数:
class AlgorithmInterface
{
public:
double operator()() {return this->ComputeSomething();}
private:
virtual double ComputeSomething() = 0;
}
class AlgorithmImplementation1: public AlgorithmInterface
{
virtual double ComputeSomething() { /* implementation */}
public:
AlgorithmImplementation1(Parameter 1);
}
class AlgorithmImplementation2: public AlgorithmInterface
{
virtual double ComputeSomething() { /* implementation */}
public:
AlgorithmImplementation2(Item a1,Item a2);
}
int main()
{
AlgorithmImplementation2 job(Item(12), Iterm(13));
double result = job(); // execute;
}
答案 1 :(得分:3)
(基于我对您的问题的理解)如果计算保持不变且只是参数类型不同,那么您可以使用templates ..
答案 2 :(得分:1)
要么使用经典的OO(运行时)多态,在这种情况下,参数需要是基类指针/引用,可以将派生类对象传递给它,或者切换到模板和编译时多态,如STL所做的那样,并将算法和参数作为模板参数的实例传递。
使用模板,这就是您的代码的样子:
class AlgorithmImplementation1
{
public:
virtual double ComputeSomething(Param1* parameter) const
{ /* implementation */}
}
class AlgorithmImplementation1
{
public:
virtual double ComputeSomething(Param2* parameter) const
{ /* implementation */}
}
template< typename Algorithm >
void use_algorithm(const Algorithm& algorithm)
{
// ...
// get_parameter() _must_ return whatever the algorithm takes
double d = algorithm( get_parameter() );
// ...
}
Param1 get_parameter();
void f()
{
use_algorithm( AlgorithmImplementation1() );
}
答案 3 :(得分:1)
另一种可能性是将“参数流”传递给算法。算法可以引用ParameterStream。
然后,派生算法将相应地从流中提取适当类型(数量)的参数。该流实现了参数的类型安全提取(反序列化),也可以实现(如果需要)版本控制。
这种可能性恕我直言的优势在于,即使将来不同的算法需要不同数量的参数,您也可以保持接口不可变。
所以基本上你会发送一个包含所需参数的序列化形式的参数,并在算法实现中根据需要对它们进行反序列化/验证。
如前所述,如果在编译时事情明确,模板也可以选择。
答案 4 :(得分:0)
你真的需要继承吗?如果你这样做,那么模板化功能将不是一个选项(即你不能拥有虚拟功能模板 - 至少在当前标准中)并且Martin的解决方案可以工作。如果你不需要继承,那么下面就足够了
class AlgorithmImplementation1
{
public:
template <typename ParamType>
double ComputeSomething(ParamType const& parameter) { /* implementation */}
}
class AlgorithmImplementation2
{
public:
template <typename ParamType>
double ComputeSomething(ParamType const& parameter) { /* implementation */}
}
这当然取决于您计划如何使用parameter
,如果您{{1},您可能最好使用重载(例如,将int
与string
区别对待)有一个一致的接口,那么函数模板就足够了。