【问题标题】:Efficient way to handle identical functions but with different operators in C处理相同功能但在 C 中使用不同运算符的有效方法
【发布时间】:2014-08-12 17:19:20
【问题描述】:

假设在 C 语言中,我有 2 个完全相同的方法,但 1 个添加值,另一个减去它:

void decreaseValue(handle* myData, uint8_t amount)
{
    /* Stuff going on */
    myData->someAttribute -= amount;
    /* Stuff going on */
}

void increaseValue(handle* myData, uint8_t amount)
{
    /* Stuff going on */
    myData->someAttribute += amount;
    /* Stuff going on */
}

除了操作符之外,这两个函数是完全一样的,导致很多行重复的代码,这不是微不足道的。

是否有一种安全、便携、不丑陋的方式来处理这个问题,或者我被 ctrl+c ctrl+v 卡住了?

开关盒的可能性:

typedef enum
{
    ADD,
    SUBSTRACT
}operator;

void modifyValue(handle* myData, uint8_t amount, operator op)
{
    /* Stuff going on */
    switch(op){
    case ADD: 
        myData->someAttribute += amount;
        break;
    case SUBSTRACT:
        myData->someAttribute -= amount;
        break;
    /* Stuff going on */
}

它有效,但感觉没有任何好转。

【问题讨论】:

  • switch - case 声明?这需要函数接受一个额外的参数。
  • 因为减法与添加负值相同,所以我会考虑以这种方式传递负值,您保留一种方法
  • @meda 你应该把它变成我认为你是对的答案。我可以将 2 个函数合并到 modify(handle* myData, int8_t amount) 中,用户将传递负值,而不必模拟多态性或决定调用哪个函数。

标签: c operators


【解决方案1】:

这个怎么样:

static inline void changeValue(handle* myData, int amount)
{
    /* Stuff going on */
    myData->someAttribute += amount;
    /* Stuff going on */
}

void increaseValue(handle* myData, uint8_t amount)
{
    changeValue(myData, (int)amount);
}

void decreaseValue(handle* myData, uint8_t amount)
{
    changeValue(myData, -(int)amount);
}

【讨论】:

  • 你让我意识到我绝对没有理由首先传递一个具有 2 个不同函数的无符号值。我了解您的解决方案是如何量身定制的,因此我不必更改我的界面。我想我的问题陷入了 XY 问题。
  • @Asics:没问题 :) ... XY 问题 是什么?
  • 当您遇到问题 X 和部分解决方案 Y 并且没有找到解决 X 的更好方法时,您尝试将 Y 重构为更优雅的解决方案,而它并不能很好地解决核心问题。 meta.stackexchange.com/questions/66377/what-is-the-xy-problem
【解决方案2】:

enum 怎么样?

typedef enum
{
    SUBTRACT,
    ADD,
    ...
} enumOperator;

void modifyValue(handle* myData, uint8_t amount, enumOperator operator)
{
    switch(operator)
    {
        case SUBTRACT:
            myData->someAttribute -= amount;
            break;
        case ADD:
            myData->someAttribute += amount;
            break;
        case ...:
            ...;
            break;
    }
}

【讨论】:

    【解决方案3】:

    使用预处理器:

    #define modifyValue(name, operator)                  \
        void name##Value(handle* myData, uint8_t amount) \
        {                                                \
            /* Stuff going on */                         \
            myData->someAttribute operator= amount;      \
            /* Stuff going on */                         \
        }
    
    modifyValue(increase, +)
    modifyValue(decrease, -)
    

    【讨论】:

      【解决方案4】:

      创建两个函数

      void addAmount(handle* myData, uint8_t amount)
      {
          myData->someAttribute += amount;    
      }
      
      void subtractAmount(handle* myData, uint8_t amount)
      {
          myData->someAttribute -= amount;    
      }
      

      创建一个可以接受上述函数之一作为参数的 genericFunction。

      void genericFunction(handle* myData, uint8_t amount,
                           void (*fun)(handle*, uint8_t))
      {
          /* Stuff going on */
      
          /* Call the function */
          fun(myData, amount);
      
          /* Stuff going on */
      }
      

      使用addAmountsubtractAmount 致电genericFunction

      genericFunction(mData, amount, addAmount);
      

      【讨论】:

        【解决方案5】:

        如果您的方法足够小,最好不要调用任何不必要的函数。使用 if-else 或 switch。

        【讨论】:

          【解决方案6】:
          void doStuff(handle* myData, uint8_t amount, void (*func)(handle*, uint8_t))
          {
              /* Stuff going on */
              func(myData, amount);
              /* Stuff going on */
          }
          

          然后像这样使用它:

          void decrease(handle* myData, uint8_t amount) { myData->someAttribute -= amount; }
          void increase(handle* myData, uint8_t amount) { myData->someAttribute += amount; }
          
          void decreaseValue(handle* myData, uint8_t amount)
          {
              doStuff(myData, amount, decrease);
          }
          void increaseValue(handle* myData, uint8_t amount)
          {
              doStuff(myData, amount, increase);
          }
          

          基本上,您在 C 中使用等效的委托(或 lambda)。doStuff 执行将被复制的实际事情。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-02-19
            • 1970-01-01
            • 1970-01-01
            • 2020-04-19
            • 1970-01-01
            • 2020-08-26
            相关资源
            最近更新 更多