我手头的任务是编写一个系统来测试库中n
个不同的算法 - 所有这些算法都执行相同的广泛任务但使用不同的方法。我想创建一个main
类,我发送一个定义要使用的算法的参数。此main
类依次调用传递要使用的参数的taskAlgorithm
类以及要使用的算法所需的输入参数。然后taskAlgorithm
类应该实例化要在其构造函数中使用的特定算法类。 taskAlgorithm::Process
应运行算法并存储结果,taskAlgorithm::Result
应返回结果。
我一直在想弄清楚如何写这个taskAlgorithm
课程。在此类的构造函数中,基于algorithmCode
参数,我想实例化特定算法的对象,但是,所有算法类都不同,并且不一定具有公共基类。解决这个问题的最佳方法是什么?
具体在
taskAlgorithm::taskAlgorithm(int algorithmCode, int argument1){
if(algorithmCode == 1){
//instantiate the algorithm1 object
}
else if(algorithmCode == 2){
//instantiate algorithm2 object
}
}
如果它们不一定共享一个公共基类,我应该如何为每个不同的算法类实例化对象?
答案 0 :(得分:2)
如果它们是相关的算法,也许你可以想到"普通"如果你知道要使用哪些部分,或者要执行哪些转换,那么如果它存在,它将能够调用任何算法。
这将允许您为所有算法编写包装器接口,因此可以统一调用它们。每个包装器都可以知道"如何使用其输入来调用它包装的底层算法。我没有在这里做,但你可以为返回值做同样的事情。
例如,算法A是将一对迭代器转换为int的向量和比较器的排序,而算法B是一种不同类型的排序,带有指向int数组,长度和比较器的指针。
class Algo {
public:
using Iter = std::vector<int>::iterator;
using Compare = ...;
virtual void call(Iter b, Iter e, Compare comp) = 0;
virtual ~Algo() = default;
};
class A : public Algo {
void call(Iter b, Iter e, Compare comp) override {
algorithmA(b, e, comp);
}
};
class B : public Algo {
void call(Iter b, Iter e, Compare comp) override {
if (b != e) {
algorithmB(&*b, std::distance(b, e), comp);
}
}
};
现在你可以用A类包装算法A,用B类包装算法b,并且它们被相同地调用,并且包装器共享一个公共基类,因此可以多态地使用它们。
当然,您无法对虚函数进行模板化,因此迭代器类型是固定的,但此处的示例是关于创建一个包装器层次结构,以规范化算法的接口。然后你可以避免讨厌的switch语句(这需要在每次添加新算法时编辑工作代码。)使用类包装器方法,只需用新的包装器类包装新算法,它应该适合任何已经使用的系统现有算法(假设您不改变虚拟调用()函数的签名)。
这并没有完全回答你的问题,但我认为它足够接近可能有用。 :)
答案 1 :(得分:1)
根据问题的评论,我认为在这种情况下,这是唯一合理的方法:
// structure of all possible arguments to all your algorithms
struct AlgorithmArgs {
int arg1;
int arg2; // etc ...
}
class AlgorithmWrapper {
public:
AlgorithmWrapper(int algorithmId, const AlgorithmArgs args) {
if (algorithmId == 1) {
algorithm_ = Algorithm1{}; // or whatever you do to construct that Algorithm1 object
} else if ( /* etc ... */ ) {}
}
void someMethodToUnifyAllAlgorithmInterfaces1();
void someMethodToUnifyAllAlgorithmInterfaces2();
void someMethodToUnifyAllAlgorithmInterfaces3();
private:
std::variant<Algorithm1, Algorithm2, Algorithm3> algorithm_;
};
taskAlgorithm::taskAlgorithm(int algorithmCode, int argument1){
AlgorithmArgs args;
args.arg1 = argument1;
algorithmWrapperPtr_ = new AlgorithmWrapper(algorithmCode, args);
executeSomeUnifiedProcedureCommonForAllAlgorithms();
}