如何使用面向对象来通用地表示参数?

发布于 2024-10-09 23:14:25 字数 628 浏览 4 评论 0原文

在 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* 作为示例,只是因为我不知道如何表示它。请告诉我应该如何执行此操作:我应该为参数创建等效继承并强制转换它们吗? (这对我来说似乎很难看)

In C++, I have to implement several algorithms, which represent different ways to compute the same thing.

I thought about using an interface to represent the different algorithm.

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 */}
}

However the parameter (a void* in the previous example) for each of these are different, how can I represent them generically ?

I used a void* for the example, just because I do not know how to represent this. Please tell me how I should do this: should I make the equivalent inheritance for the parameters and cast them ? (this seems ugly to me)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

泪痕残 2024-10-16 23:14:25

您可以在构造函数中传递参数。
另外,将虚拟成员设置为私有并使该对象成为函子:

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;
}

You can pass the parameters in the constructor.
Additionally make the virtual member private and make the object a functor:

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;
}
可是我不能没有你 2024-10-16 23:14:25

(根据我对你的问题的理解)如果计算保持不变,只是参数类型不同,那么你可以使用 模板..

(Based on my understanding of your question) If the computation remains the same and just the parameter types vary, then you can use templates..

锦欢 2024-10-16 23:14:25

另一种可能性是将“参数流”传递给算法。算法可以引用 ParameterStream。

然后,派生算法将从流中相应地提取适当类型(数量)的参数。该流实现参数的类型安全提取(反序列化),并且还可以实现(如果需要)版本控制。

恕我直言,这种可能性的优点是,即使将来不同的算法需要不同数量的参数,您也可以保持接口不变。

因此,基本上,您将发送一个包含所需参数的序列化形式的参数,并在算法实现中根据需要对它们进行反序列化/验证。

正如前面的海报所提到的,如果在编译时事情很清楚,模板也可以是一个选项。

One other possibility would be to pass in a "parameter stream" to the algorithms. An algorithm could take a reference to a ParameterStream.

The derived algorithms would then extract the appropriate types (number) of parameters from the stream accordingly. The stream implements type safe extraction (de-serialization) of the parameters, and could also implement (if desired) versioning.

This possibility would IMHO have the advantage that you can keep the interface immutable even if in the future different algorithms will need a different number of parameters.

So basically you would send a parameter that contains a serialized form of the parameters you need and you de-serialize/validate them as you need them in the algorithm implementation.

As mentioned by the previous posters templates could also an option if things are clear cut at compile time.

九歌凝 2024-10-16 23:14:25

要么使用经典的 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() );
}

Either you use classic OO (run-time) polymorphism, in which case the parameter needs to be a base class pointer/reference, to which derived class objects can be passed, or you switch to templates and compile-time polymorphism, as the STL does, and pass the algorithm and the parameter as an instance of a template parameter.

With templates, this is what your code might look like:

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() );
}
樱&纷飞 2024-10-16 23:14:25

真的需要继承权吗?如果这样做,那么将函数模板化将不是一个选项(即您不能拥有虚拟函数模板 - 至少在当前标准中),并且 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,您最好使用重载(例如, treat int code> 与 string 不同),如果您的 parameter 具有一致的接口,那么函数模板就足够了。

Do you really need the inheritance? If you do, then templating the function will not be an option (i.e. you cannot have a virtual function template - at least in the current standard) and Martin's solution works. If you don't need inheritance, then the below should suffice

class AlgorithmImplementation1
{
  public:
    template <typename ParamType>
      double ComputeSomething(ParamType const& parameter) { /* implementation */}
}

class AlgorithmImplementation2
{
  public:
    template <typename ParamType>
      double ComputeSomething(ParamType const& parameter) { /* implementation */}
}

This of course depends on how you plan to use parameter, you may be better off using overloading (for example, treat int different to string), if your parameter has a consistent interface then the function template will suffice.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文