关于C#:对象构造:默认参数vs委托

object construction : default parameter vs delegation

考虑以下代码,在这里我尝试引入默认构造函数以及class A的参数化构造函数。最近的c改进中引入了这种方法。

1
2
3
4
5
6
7
8
class A  {
    private:
        unsigned int count;

    public:
        A(int new_c) : count(new_c) {}
        A() : A(10) {}
};

与在参数化构造函数上设置默认参数并完全忽略默认构造函数的旧方法相比。

1
2
3
4
5
6
7
class A  {
    private:
        unsigned int count;

    public:
        A(int new_c = 5) : count(new_c) {}
};

与遵循第二种约定相比,使用第一种方法要比第二种方法有什么优势吗?


在功能上没有区别。要知道,非静态成员初始化还有另一个选项可用(自C 11起):

1
2
3
4
5
6
7
8
class A  {
    private:
        unsigned int count = 10;

    public:
        A() = default;
        A(int new_c) : count(new_c) {}
};

在您的示例中,这种情况没有任何优势(在该示例中,我甚至会选择第二个选项,以便更清楚地了解该问题)

在默认值不足的情况下添加的委托构造函数,以简化工作。

例如

1
2
3
4
5
struct Point3d
{
   Point3d(int x, int y, int z);
   Point3d(Point2d p) : Point3d(p.x, p.y, 0) {}
}

从技术上讲没有区别,但是创建转发构造函数的想法却不同。
想象一下下面的类:

1
2
3
4
5
6
7
8
9
10
11
12
class sample {
    complexType member;
    bool createdWithInt;
public:
    sample() : member(5), createdWithInt(false) {
       /* code ... */
    }
    sample(int param) : sample() {
       createdWithInt = true;
       /* other code */
    }
};

因此,此类很难使用默认参数实现:
其行为不取决于参数的值,而取决于存在性。

可能会尝试使用一个辅助函数void creator()来实现它,该函数执行不带参数的构造函数中的code ...位。但是,这将意味着复制初始化列表(或者如果从creator()内部进行初始化,则放弃RAII原理)。

注意:createdWithInt可以从初始化列表中进行初始化,如果添加了另一个构造函数,则该构造函数将bool和两个当前构造函数都转发到该构造函数。为了便于说明,已将其省略。


在较大的类(可以是几个构造函数)的情况下,优势会更加明显。用新的方式,您将能够编写一个构造函数,然后将其设置为其他构造函数。这不太容易出错。

1
2
3
4
5
6
7
8
9
10
11
12
class A  {
    private:
        unsigned int count;
        int other;
        float otherfloat;


    public:
        A( unsigned int count, int other, float otherfloat ) : count( count), other( other ), otherfloat( otherfloat ) {}
        A(int new_c) : A(new_c, 0, 0.0 ) {}
        A() : A(10) {}
};