【问题标题】:How can I decrease the number of overloaded functions如何减少重载函数的数量
【发布时间】:2022-02-02 21:32:42
【问题描述】:

我想知道下面代码中是否有减少重载函数(函数编辑)数量的方法。

 class foo
  {
  public:
      foo(int _a, char _b, float _c) : a(_a), b(_b), c(_c){};
      void edit(int new_a);
      void edit(char new_b);
      void edit(float new_c);
      void edit(int new_a, char new_b);
      void edit(int new_a, float new_c);
      void edit(char new_b, float new_c);
      void edit(int new_a, char new_b, float new_c);
      void info();
  private:
     int   a;
     char  b;
     float c;
  };

这里是编辑功能的实现:

void foo::edit(int new_a)
{
    a = new_a;
}
void foo::edit(char new_b)
{
    b = new_b;
}
void foo::edit(float new_c)
{
    c = new_c;
}
void foo::edit(int new_a, char new_b)
{
    a = new_a;
    b = new_b;
}
void foo::edit(int new_a, float new_c)
{
    a = new_a;
    c = new_c;
}
void foo::edit(char new_b, float new_c)
{
    b = new_b;
    c = new_c;
}
void foo::edit(int new_a, char new_b, float new_c)
{
    a = new_a;
    b = new_b;
    c = new_c;
}

编辑功能可以让用户随意更改对象的参数。 但问题是,如果我们添加一个新参数,我们必须添加许多重载函数,我认为应该有更好的方法。

这里有 3 个参数,我们需要 7 个重载函数,但如果我们有 4 个参数(a、b、c 和 d),那么我们必须开发 14 个重载函数! 这就是为什么我认为应该有更好的方法。

谢谢。

【问题讨论】:

  • 您可以将其设为成员函数模板,但除非您向我们展示这些edit 成员函数的实现,否则我们无法肯定地说/建议任何事情。跨度>
  • 假设 foo 类是一个联系人管理器,并且该类的每个对象都包含诸如(姓名、电话、电子邮件)之类的参数,并且编辑功能旨在更改这些参数,但您可能不想更改所有参数,也许您需要更改(电话和姓名)或仅更改(电话)或仅更改(姓名),以便您有不同的选项来更改参数。你明白我的意思了吗?
  • 让编辑返回对this 的引用,这样你就可以链接它们:f.edit(1).edit(1.0); 那么你就不需要组合重载。如果设置多个值需要依赖于两个参数的检查,则使用相同的方法,但 edit 返回一些执行检查的代理
  • 如果我理解您对此代码的注释解释,任何对edit() 的多个参数调用与对edit() 的多次调用具有相同的效果,每个调用都有一个参数?如果这是正确的,edit 你的问题可以更好地描述你正在解决的问题。
  • @meysamimani 请edit你的问题是完整的。

标签: c++ overloading


【解决方案1】:

std::tuple 上使用可变参数和(ab)使用std::get<T>,您可能会这样做

template <typename... Ts>
void edit(Ts... values)
{
    ((std::get<Ts&>(std::tie(a, b, c)) = std::get<Ts&>(std::tie(values...))), ...);
}

Demo.

注意:我使用std::get&lt;Ts&amp;&gt;(std::tie(values...)) 而不是简单的values 来获取重复输入类型的错误(edit(42, 42);)。

【讨论】:

  • ͏+͏1͏͏͏͏͏͏͏͏͏͏͏͏͏
  • 为什么我是唯一的支持者?这是本周迄今为止最优雅的答案。
  • @Bathsheba:新年伊始,我什至希望今年 ;-)
  • 是否有一些日历刚刚凝视了新千年? :P
【解决方案2】:

您可以避免大量的重载,并且仍然允许调用者在单个表达式中设置多个成员:

class foo
  {
  public:
      foo(int _a, char _b, float _c) : a(_a), b(_b), c(_c){};
      foo& edit(int new_a) { a = new_a; return *this;}
      foo& edit(char new_b) { b = new_b; return *this; }
      foo& edit(float new_c) { c = new_c; return *this; }
      
  private:
     int   a;
     char  b;
     float c;
};

int main() {
    foo f(1,'c',2.0);
    f.edit(42).edit(42.0f).edit('a');
}

添加成员需要您编写一个重载而不是 N 以支持所有组合。

【讨论】:

    【解决方案3】:

    以前的解决方案都很好,但假设所有元素都有不同的类型。

    一种可能性是仍然使用可变参数模板,并在调用中用string 指示必须修改哪个元素。
    这将允许为不同的元素使用相同的类型。

    #include <iostream>
    #include <string>
    
    class foo {
      public:
          foo(int _a, char _b, float _c) : a(_a), b(_b), c(_c){};
          void edit() {};
          template<typename T1, typename... T2>
          void edit (const std::string& id, T1 var1, T2... var2) {
              if (id == "a") a = var1;
              else if (id == "b") b = var1;
              else if (id == "c") c = var1;
              edit(var2...);
          };
          void info();
      //private:
         int   a;
         char  b;
         float c;
    };
    
      std::ostream& operator<<(std::ostream& os, const foo& obj) {
        std::cout << "a = " << obj.a <<  " b = " << obj.b << " c = " << obj.c;
        return os;
      }
    
    int main() {
        foo example(1, 'a', 2.0);
        example.edit("c", 3.0f, "b", 'g', "a", 5);
        std::cout << example << std::endl;
    }
    

    【讨论】:

      【解决方案4】:

      鉴于您的 edit 修改单个成员的函数:

      void edit(int new_a)
      {
          a = new_a;
      }
      void edit(char new_b)
      {
          b = new_b;
      }
      void edit(float new_c)
      {
          c = new_c;
      }
      

      您可以在 C++11 中使用variadic templates 定义单个函数,以支持单个参数的多个调用:

      template< typename FirstType, typename ...OtherTypes >
      void edit(FirstType ft, OtherTypes ...ot)
      {
          edit(ft);
          edit(ot...);
      }
      

      使用C++17fold expressions可以让这个功能更加简单。

      template< typename ...Types >
      void edit(Types ...types)
      {
          (edit(types), ...);
      }
      

      注意:此解决方案不会尝试防止对同一类型进行多次更改,例如edit(1, 2, 3);

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-10-19
        • 2021-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-08-15
        • 2012-01-30
        相关资源
        最近更新 更多