【问题标题】:Algorithm for modular function performing different operations?执行不同操作的模块化函数的算法?
【发布时间】:2013-12-22 08:42:05
【问题描述】:

有时我会遇到需要多次执行一组代码但稍作修改的情况。考虑以下两种情况:

Case 1:
A
B
C

Case 2:
A
D
C

//A, B, C, D are used to represent a set of code lines

现在BD 中的代码行之间没有相似之处,因此我目前在我的应用程序中创建了 2 个不同的函数。 但是BD 中的代码大小与AC 相比非常小。 我不能只为AC 创建单独的函数,因为它们使用一些公共变量,并且将这些变量作为参数传递会非常混乱。

所以看起来我的问题只有一个解决方案。 将这两种情况组合成一个函数,并通过将bool 作为参数传递给该函数来在其中一种情况之间进行选择。然而,这导致要维护的功能非常大。 所以我正在寻找一些更好的选择,因为我相信很多人一定遇到过这种情况。

编辑: 为了简单起见,考虑一个字符串变量myString

A intialises it with some value.

B/D modify it according to some conditions.

C uses myString for some purpose, say write to file.

总而言之,数据流是这样的:

Case 1:
A -> B -> C

Case 2:
A -> D -> C

只是有大量数据流将这些集合中的每一个分成不同的功能。

【问题讨论】:

  • 是否可以定义一个适用于 B 和 D 的抽象函数签名?然后你可以传递一个函数指针来执行中间部分。
  • “我不能只为 A & C 创建单独的函数,因为它们使用一些公共变量,并且将这些变量作为参数传递会非常混乱。” - 对不起,这就是重构的工作方式。有时很难。而且你无法真正避免它。
  • @H2CO3 - OP 表示 A 和 C 共享公共变量;我问的是 B 和 D。也许 OP 意味着 A 和 C 与 B 和 D 共享太多,但这不是所说的。
  • @TedHopp 您能否通过代码说明“定义一个适用于 B 和 D 的单一抽象函数签名”是什么意思?
  • @TedHopp 是 A 和 C 与 B/D 共享变量。这就是为什么 B/D 介于 A 和 C 之间的原因。

标签: c++ algorithm optimization


【解决方案1】:

我能想到的选项:

  • 创建一个以 A、B、C 和 D 为函数的类。

    所有的公共变​​量都可以是这个类的成员变量。

  • 创建一个简单地存储所有公共变量的类。

    这可以通过引用 A、B、C 和 D 来传递(因此您只需传递一个变量)。

  • 考虑尝试重构它们,以尽量减少它们使用的公共变量的数量。

    这可以在上述任何一个之外完成,也可以单独完成。

    在不知道你到底在做什么的情况下,我无法真正告诉你这是否可行,但你应该记住这一点。虽然上面提到的参数类只是一个变量,但它本质上只是一堆变量的包装器——仍然应该尽量减少它们的数量。

【讨论】:

  • 如果对同一个类对象有大量调用,您的解决方案是可以接受的。但在我的情况下,如果我创建类,那么该对象将只有 2 次调用。似乎很少创建一个新的类来运行一些代码。但正如你所说,在看到代码之前你不能给出具体的解决方案。感谢您提供可行的解决方案。
  • @Cool_Coder 如果 A 和 C 真的和你说的一样大,我认为把这一切都放在一个类中一点也不坏。不要陷入类必须是“对象”或其他任何东西的思维框架中:如果代码更干净、更简单、更快,那么就这样做......我设想类似,类有一个 populate 函数,用于设置传递给 A 的所有数据等,并有 ABCD 以自然方式调用的函数。
  • @Cool_Coder 老实说,在普通 C 中可能会解决这个问题的方法是创建一个 struct 来保存函数共有的数据,并且指向它的指针会得到绕过。您也可以采用这种方法。然而,拥有一个怪物大小的函数似乎可能是所有方法中最糟糕的。
【解决方案2】:

您可以做的一件事是将 B 和 D 定义为仿函数类:

// this is a functor
struct B_add {
  B_add(int x) : x_(x) {}
  int operator()(int y) { return x_ + y; }
  void set_x(int x) { x_ = x; }

private:
  int x_;
};

struct D_mult {
  D_mult(int x) : x_(x) {}
  int operator()(int y) { return x_ * y; }
  void set_x(int x) { x_ = x; }

private:
  int x_;
};

然后在long_function_that_takes_either_B_or_D里面

template <typename F> 
void long_function_that_takes_either_B_or_D(F & f) 
{
    A...

    f.set_x(result_of_a);
    int result_for_c = f(); //B or D

    C...
}

主要:

int main(int argc, char **argv) {
    long_function_that_takes_either_B_or_D(B_add(42));
    long_function_that_takes_either_B_or_D(D_mult(24));
    return 0;
}

【讨论】:

    【解决方案3】:

    它阻碍了面向对象的设计,但我认为你可以尝试将它安排到一个类中

    #include <stdio.h>
    
    class SimpleClass
    {
        public:
        SimpleClass(void){}
        void someFunction(void (* zprintf)(const char *) ) //zprintf is pointer to  B or D functionality
        {
            printf("calling zprintf function\n"); //This is your A code
            zprintf("hey");
            printf("called zprintf function\n"); //This is your C code
        }   
        ~SimpleClass(void)
         {}
    };
    

    然后像这样使用它:

    void zprintf1(const char * str )
    {
        printf("i'm printing %s\n", str);
    }
    
    
    void zprintf2(const char * str )
    {
       printf("I don't want to print %s\n", str);
    }
    

    。 . .

    SimpleClass simpleClass;
    simpleClass.someFunction(zprintf1);
    simpleClass.someFunction(zprintf2);
    

    我知道这是一个 hack,但你可以让它更漂亮。

    【讨论】:

      【解决方案4】:

      使用定义生成代码。

      // A
      if (runB)
          // B
      else 
          // D
      // C
      

      【讨论】:

      • 我不明白这如何回答我的问题。
      • 我根据你的问题修改编辑,希望你现在明白
      • "所以看起来我的问题只有一个解决方案。将这两种情况合并到一个函数中,并通过将布尔值作为参数传递给该函数来在其中一种情况之间进行选择。然而,这导致要维护的功能非常大。所以我正在寻找一些更好的替代方案,因为我相信很多人一定遇到过这种情况。您的建议已经是我在问题中提到的内容。
      • 告诉我为什么上面的(编辑的)解决方案不能解决它?
      • 因为如果A、B、C、D都在一个函数中,那么函数的规模太大了,不容易维护。这也违反了模块化原则。
      猜你喜欢
      • 2015-04-05
      • 1970-01-01
      • 2012-07-04
      • 1970-01-01
      • 2017-04-07
      • 2021-04-29
      • 1970-01-01
      • 1970-01-01
      • 2011-09-30
      相关资源
      最近更新 更多