【问题标题】:Overloading constructor with 2 same datatype members重载具有 2 个相同数据类型成员的构造函数
【发布时间】:2020-05-24 15:53:20
【问题描述】:

假设我有一个包含两个 std::string 成员和一个 int 值的类,例如:

class DataGroup final {
 public:
  explicit DataGroup (const std::vector<int>& groupNr,
                                   const std::string& group1,
                                   const std::string& group2)
      : groupNr(groupNr)
      , group1(group1)
      , group2(group2){};

  std::vector<int> groupNrs{};
  std::string group1{};
  std::string group2{};
};

我能否以某种方式拥有 2 个重载的构造函数,其中一个将初始化 groupNr 和 group1,而其他 ctor 初始化 groupNr 和 group2?在 ctor 调用中未初始化的字符串之一将是空字符串。

【问题讨论】:

  • 您能否举例说明如何使用它,即您想如何使用不同的构造函数?
  • 当然可以,但是如果你不显式初始化任何成员变量,编译器会为你生成默认初始化。依赖它可能会导致意想不到的结果。
  • @cigien 如果我可以始终使用一个或另一个字符串调用构造函数,那就太好了,即 int a = 2;诠释 b = 3; std::vector dataGroupList{}; dataGroupList.emplace_back(a, "group1 的东西"); dataGroupList.emplace_back(b, "group2 的东西");
  • 但是构造函数的第一个参数需要vector&lt;int&gt;,而不是int

标签: c++ constructor-overloading


【解决方案1】:

有几种方法可以产生预期的行为:

  • 命名构造函数

    class DataGroup final {
    public:
        // ...
        static DataGroup Group1(const std::vector<int>& groupNr,
                          const std::string& group)
          { return DataGroup{groupNr, group, ""}; }
        static DataGroup Group2(const std::vector<int>& groupNr,
                          const std::string& group)
          { return DataGroup{groupNr, "", group}; }
    
        // ...
    };
    
    DataGroup d = DataGroup::Group2({1, 2}, "MyGroup");
    
  • 标记的构造函数

    struct group1{};
    struct group2{};
    class DataGroup final {
    public:
        // ...
        DataGroup(group1, const std::vector<int>& groupNr,
                          const std::string& group) : DataGroup{groupNr, group, ""} {}
        DataGroup(group2, const std::vector<int>& groupNr,
                          const std::string& group) : DataGroup{groupNr, "", group} {}
    
        // ...
    };
    
    DataGroup d{group2{}, {1, 2}, "MyGroup");
    
  • 命名参数(请参阅there 了解可能的实现方式)

    // ...
    DataGroup d{groupNr = {1, 2}, group2 = "MyGroup");
    

【讨论】:

    【解决方案2】:

    为了重载函数/构造函数,它们必须有 2 个不同的签名。由于两种情况下要提供的预期类型相同,因此您必须提供第三个参数,其中一个可能具有默认值。但同样,请注意未初始化的本地字段,因为它们将由编译器生成的代码自动初始化。

    【讨论】:

    • 你是说如果我希望其中一个为空,例如我应该用 "" 初始化每个字符串吗?
    • 返回类型对于重载决议无关紧要。默认初始化器有什么不好?
    • 这取决于你要初始化什么,对我来说它会更明确。
    • @churill 他们被隐藏了。
    • @churill 是的,抱歉,返回类型不计入重载。
    【解决方案3】:

    这里的解决方案之一是简单地使用带有“通用”成员的基类

    groupNr(groupNr)
    

    每个派生类中都有另外两个独立的成员,那么在初始化派生类时,你可以通过调用基类的构造函数来初始化基类成员groupNr:

    class DataGroup {
     public:
      explicit DataGroup (const std::vector<int>& groupNrs)
          : groupNrs(groupNr){};
    
      std::vector<int> groupNrs{};
    };
    
    class DataGroup1 : public DataGroup {
     public:
      explicit DataGroup1 (const std::vector<int>& groupNrs,
                                       const std::string& group1)
          : DataGroup(groupNrs)
          , group1(group1){};
    
      std::string group1{};
    };
    
    class DataGroup2 : public DataGroup {
     public:
      explicit DataGroup2 (const std::vector<int>& groupNrs,
                                       const std::string& group2)
          : DataGroup(groupNrs)
          , group2(group2){};
    
      std::string group2{};
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-09
      • 1970-01-01
      相关资源
      最近更新 更多