C++传递大量参数的设计模式

发布于 2024-10-30 07:07:04 字数 1036 浏览 1 评论 0原文

我有一个大小合理的类,它实现了几种逻辑相关的算法(来自图论)。算法需要大约 10-15 个参数作为输入。这些不被算法修改,而是用于指导算法的操作。首先,我解释实现此目的的两个选项。我的问题是这样做的常见方法是什么(无论是还是不是这两个选项之一)。

当 N 很大时,我个人不喜欢将这些值作为参数传递给函数,尤其是当我仍在开发算法时。

void runAlgorithm(int param1, double param2, ..., bool paramN);

相反,我有一个包含算法的类Algorithm,并且我有一个包含这些参数的结构AlgorithmGlobals。我要么将此结构传递给:

void runAlgorithm(AlgorithmGlobals const & globals);

要么将一个公共 AlgorithmGlobals 实例添加到类中:

class Algorithm {
public:
    AlgorithmGlobals globals;
    void runAlgorithm();
}

然后在其他地方我会像这样使用它:

int main() {
    Algorithm algorithm;
    algorithm.globals.param1 = 5;
    algorithm.globals.param2 = 7.3;
    ...
    algorithm.globals.paramN = 5;

    algorithm.runAlgorithm();

    return 0;
}

请注意,AlgorithmGlobals 的构造函数为每个参数定义了良好的默认值,因此仅需要指定非默认值的参数。

AlgorithmGlobals 未设为私有,因为它们可以在调用 runAlgorithm() 函数之前自由修改。没有必要“保护”他们。

I have a reasonably-sized class that implements several logically-related algorithms (from graph theory). About 10-15 parameters are required as input to the algorithm. These are not modified by the algorithm, but are used to guide the operation of it. First, I explain two options for implementing this. My question is what is a common way to do so (whether it is or isn't one of the two options).

I personally don't like to pass these values as parameters to the function when N is large, especially while I'm still developing the algorithm.

void runAlgorithm(int param1, double param2, ..., bool paramN);

Instead I have a class Algorithm that contains the algorithms, and I have a struct AlgorithmGlobals that contains these parameters. I either pass this struct to:

void runAlgorithm(AlgorithmGlobals const & globals);

Or I add a public AlgorithmGlobals instance to the class:

class Algorithm {
public:
    AlgorithmGlobals globals;
    void runAlgorithm();
}

Then elsewhere I'd use it like this:

int main() {
    Algorithm algorithm;
    algorithm.globals.param1 = 5;
    algorithm.globals.param2 = 7.3;
    ...
    algorithm.globals.paramN = 5;

    algorithm.runAlgorithm();

    return 0;
}

Note that the constructor of AlgorithmGlobals defines good defaults for each of the parameters so only the parameters with non-default values need to be specified.

AlgorithmGlobals are not made private, because they can be freely modified before the runAlgorithm() function is called. There is no need to "protect" them.

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

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

发布评论

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

评论(6

情仇皆在手 2024-11-06 07:07:04

这称为“参数对象”模式,这通常是一件好事。我不喜欢会员版本,特别是称其为“XGlobals”并暗示它在各处共享。相反,参数对象模式通常涉及创建参数对象的实例并将其作为参数传递给函数调用。

This is called the "Parameter object" pattern, and it's generally a good thing. I don't like the member version, especially calling it "XGlobals" and implying that it's shared all over the place. The Parameter Object pattern instead generally involves creating an instance of the Parameter Object and passing it as a parameter to a function call.

十秒萌定你 2024-11-06 07:07:04

其他人提到了参数对象,但还有另一种可能性:使用生成器

Builder 允许您省略默认值合适的参数,从而简化您的代码。如果您要将算法与几组不同的参数一起使用,这尤其方便。 OTOH 它还允许您重用类似的参数集(尽管存在无意重用的风险)。这(与方法链接一起)将允许您编写如下代码

Algorithm.Builder builder;

Algorithm a1 = builder.withParam1(1).withParam3(18).withParam8(999).build();
...
Algorithm a2 = builder.withParam2(7).withParam5(298).withParam7(6).build();

Others have mentioned Parameter Object, but there is also another possibility: using a Builder.

Builder allows you to omit the parameters whose default values are suitable, thus simplifying your code. This is especially handy if you are going to use your algorithm with several different sets of parameters. OTOH it also allows you to reuse similar sets of parameters (although there is a risk of inadvertent reuse). This (together with method chaining) would allow you to write code such as

Algorithm.Builder builder;

Algorithm a1 = builder.withParam1(1).withParam3(18).withParam8(999).build();
...
Algorithm a2 = builder.withParam2(7).withParam5(298).withParam7(6).build();
舟遥客 2024-11-06 07:07:04

您应该在设计中提出几种不同的想法:

  1. 参数纯粹是输入。
  2. 这些参数特定于您的算法。
  3. 参数具有合理的默认值。

class Algorithm {
  public:
    class Parameters { // Nested class, these are specific to your algorithm.
      public:
        Parameters() : values(sensible_default) { }
        type_t values; // This is all about the data.
    };

    Algorithm(const Parameters ¶ms) : params_(params) { }

    void run();

  private:
    const Parameters params_; // Paramaeters don't change while algorithm
};                            // is running. 

这就是我的建议。

You have several different ideas that you should be suggesting with your design:

  1. The parameters are purely inputs.
  2. The parameters are specific to your algorithm.
  3. The paramaters have default values that are sane.

class Algorithm {
  public:
    class Parameters { // Nested class, these are specific to your algorithm.
      public:
        Parameters() : values(sensible_default) { }
        type_t values; // This is all about the data.
    };

    Algorithm(const Parameters ¶ms) : params_(params) { }

    void run();

  private:
    const Parameters params_; // Paramaeters don't change while algorithm
};                            // is running. 

This is what I would suggest.

秋意浓 2024-11-06 07:07:04

我使用您已经提到过的这种技术:

void runAlgorithm(AlgorithmGlobals const & globals);

但会调用类 AlgorithmParams 来代替。

I use this technique that you already mentioned:

void runAlgorithm(AlgorithmGlobals const & globals);

But would call the class AlgorithmParams instead.

小…楫夜泊 2024-11-06 07:07:04

命名参数习惯用法在这里可能有用。

a.runAlgorithm() = Parameters().directed(true).weight(17).frequency(123.45);

The Named Parameter Idiom might be useful here.

a.runAlgorithm() = Parameters().directed(true).weight(17).frequency(123.45);
静水深流 2024-11-06 07:07:04

建议你为什么不这样做:

class Algorithm {
public:
Algorithm::Algorithm(AlgorithmGlobals const & globals) : globals_(globals) {}

    void runAlgorithm(); // use globals_ inside this function

   private:
    const AlgorithmGlobals globals_;
    };

现在你可以这样使用它:

AlgorithmGlobals myglobals;
myglobals.somevar = 12;

Algorithm algo(myglobals);

suggestion Why don't you do this instead:

class Algorithm {
public:
Algorithm::Algorithm(AlgorithmGlobals const & globals) : globals_(globals) {}

    void runAlgorithm(); // use globals_ inside this function

   private:
    const AlgorithmGlobals globals_;
    };

Now you can use it as such:

AlgorithmGlobals myglobals;
myglobals.somevar = 12;

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