【问题标题】:Overloading constructors with default parameters使用默认参数重载构造函数
【发布时间】:2014-01-25 00:57:26
【问题描述】:

我有一个包含 5 个变量的类:2 个字符串、2 个双精度数和一个整数。

用户将始终能够提供至少一个字符串和一个双精度,但可能无法提供其余信息,这意味着应包含默认参数。

当然,尝试使用所有参数创建一堆构造函数是行不通的——它无法编译。

假设我尝试这样的事情:

         Object(std::string s1, double d1) {
            this->string1 = s1;
            this->double1 = d1;
            this->int1 = 0;
            this->double2 = 0.0;
            this->string2 = "foo";
    }
         Object(std::string s1, double d1, int i) {
            this->string1 = s1;
            this->double1 = d1;
            this->int1 = i;
            this->double2 = 0.0;
            this->string2 = "foo";
    }

    // and so on...

这将重载构造函数,但这些仍被视为默认参数吗?

有没有办法让每个构造函数中的每个参数都包含默认参数?即,类似于这种不起作用的东西:

 Object(std::string s1, double d1, int i = 0, std::string s2 = "foo", double d2 = 0.0) {

 ...
 }
 Object(std::string s1, double d1, int i, std::string s2 = "foo", double d2 = 0.0) {

 ...
 }
 // and so on...

这样做的问题是,如果用户只有所需的 5 个值中的 4 个,则在某些时候它必须“跳过”一个参数。例如,如果我只使用了第一个字符串,而用户没有第二个字符串,那么就没有办法越过它来传递第二个双精度数。

【问题讨论】:

  • 在上一个示例中只有第一个签名有什么问题?
  • 您遇到什么错误?您在第二个示例中尝试执行的操作应该有效。
  • 没错。这就是你所需要的。你想多了。

标签: c++ class constructor


【解决方案1】:

对于具有这么多构造参数的类,我建议您使用builder pattern。这种模式基本上使用一个单独的构建器类来保存所有构造参数,然后将它们全部传递给您的真实类的构造器。

使用构建器模式,您可以在构建器内部建立默认参数值,因此如果只需要覆盖一两个参数,您的调用代码仍然可以保持简单。

(如果您在问题中使用了真实的类和参数名称,我可以编写一个示例构建器来说明这一点,但希望阅读有关构建器模式的信息会给您一个使用的想法。)

【讨论】:

    【解决方案2】:

    默认参数值在参数列表(不是函数体)中指定,如您在第二个代码示例中所示。

    你所需要的只是

    Object(std::string s1, double d1, int i = 0, std::string s2 = "foo", double d2 = 0.0)
    {
                this->string1 = s1;
                this->double1 = d1;
                this->int1 = i;
                this->double2 = s2;
                this->string2 = d2;
    }
    

    虽然,正确的 C++ 语法是使用初始化列表:

    Object(std::string s1, double d1, int i = 0, std::string s2 = "foo", double d2 = 0.0):
        string1( s1 ),
        double1( d1 ),
        int1( i ),
        double2( s2 ),
        string2( d2 )
    {
        // constructor body
    }
    

    当用户调用带有 s1 和 d1 或可选的 i、s2 和 d2 的构造函数时,将填充默认值。唯一需要注意的是它们必须按该顺序提供。不能只提供 i 和 d2,只能提供 i 和 s2,或者 i、s2 和 d2。

    Object myobject ( "s1", 0.5 );    //valid
    Object myobject ( "s1", 0.5, 9, "foo" ); //valid
    Object myobject ( "s1", 0.5, "s2" ); //invalid, skipped parameter 'i'
    

    【讨论】:

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