如何用功能相似但签名不同的方法设计class

How to design a class with methods which have similar functions but different signatures

我手头的任务是编写一个系统来测试库中的 n 不同算法 - 所有算法都执行相同的广泛任务,但使用不同的方法。我考虑过创建一个 main class 并向其发送定义要使用的算法的参数。这个 main class 又调用 taskAlgorithm class 传递要使用的参数和要使用的算法所需的输入参数。然后 taskAlgorithm class 应该实例化要在其构造函数中使用的特定算法 class。 taskAlgorithm::Process 应该 运行 算法并存储结果,taskAlgorithm::Result 应该 return 结果。

我一直在思考如何编写这个 taskAlgorithm class。在这个class的构造函数中,基于algorithmCode参数我想实例化一个具体算法的对象,但是,所有的算法class都是不同的,不一定有共同的基地 class。解决此问题的最佳方法是什么?

具体在

taskAlgorithm::taskAlgorithm(int algorithmCode, int argument1){
   if(algorithmCode == 1){
      //instantiate the algorithm1 object
   }
   else if(algorithmCode == 2){
      //instantiate algorithm2 object
   }
}

如果每个不同的算法 classes 不一定共享一个公共基础,我应该如何实例化对象 class?

根据问题下的评论,我认为在这种情况下这是唯一合理的做法:

// 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();
}

如果它们是相关算法,也许您可​​以想到 "common" 接口,如果它存在,如果您知道要使用哪些部分或哪些转换,则能够调用任何算法执行。

这将允许您为所有算法编写一个包装器接口,以便可以统一调用它们。每个包装器可以 "know" 如何获取其输入以调用它包装的底层算法。我没有在此处执行此操作,但您可以对 return 值执行相同的操作。

例如,算法 A 是一种将一对迭代器放入一个整数向量和一个比较器的排序,而算法 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);
        }
    }
};

现在你可以用 class A 包装算法 A,用 class B 包装算法 b,它们被相同地调用,并且包装器共享一个公共基础 class 所以它们可以多态使用。

当然,您不能将虚函数模板化,因此迭代器类型是固定的,但这里的示例是关于制作一个包装器层次结构来规范化算法的接口。然后你可以避免讨厌的 switch 语句(每次添加新算法时都需要编辑工作代码。)使用 class 包装器方法,只需用新包装器 class 包装新算法,它应该只是适用于任何已经使用现有算法的系统(前提是您不更改虚拟 call() 函数的签名)。

这并不能完全回答您的问题,但我认为它足够接近,可能会有用。 :)