对象构造:默认参数与委托

object construction : default parameter vs delegation

本文关键字:参数 默认 对象      更新时间:2023-10-16

考虑下面的代码,我试图为class A引入默认构造函数和参数化构造函数。在最近的c++改进中引入了这种方式。

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

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

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

除了遵循现代惯例之外,使用第一种方法比使用第二种方法有什么优势吗?

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

class A  {
    private:
        unsigned int count = 10;
    public:
        A() = default;
        A(int new_c) : count(new_c) {}
};

在像你的例子中这样的情况下没有优势(我甚至会选择第二个选项,因为在这样的例子中更清楚)

当默认值不够时,委派添加的构造函数以简化工作。

例如

struct Point3d
{
   Point3d(int x, int y, int z);
   Point3d(Point2d p) : Point3d(p.x, p.y, 0) {}
}

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

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) {}
};

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

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和两个当前构造函数转发到该构造函数。为了示例的目的,已经省略了这一点。