委派复制构造函数和 const 数据初始化

Delegating copy constructor and const data initialization

提问人:Sergey 提问时间:8/1/2017 最后编辑:Sergey 更新时间:8/1/2017 访问量:1786

问:

我有一个包含许多数据成员的类,其中一些是常量。所有数据成员都有适当的复制构造函数,所以我想默认我的类的复制构造函数:A

class A
{
public:
        A() : a(1) {}
        A(const A& op) = default;
private:
        // ... Lots of constant and non-constant member data ...
        const int a;
};

然后,我想编写一个构造函数,它接受对常量数据成员之一的引用和一个值:A

A(const A& op, const int a_);

这里应该被复制,并且应该在那之后进行初始化,或者代替复制。我想通过委托给复制构造函数来避免手动初始化所有数据成员,但是在这种情况下如何覆盖我的 const 数据成员? 例如:opaa_

// Illegal: constructor delegation can't be mixed with field initialization.
A(const A& op, const int a_) : A(op), a(a_) {}

// Illegal: attempt to assign constant member.
A(const A& op, const int a_) : A(op) { a = a_; } 

// Hack. May lead to UB in some cases.
A(const A& op, const int a_) : A(op)
{
    *(const_cast<int*>(&a)) = a_;
    // ... or same tricks with memcpy ...
}

显然,所有这些方法都是邪恶的,因为它们试图初始化两次。a

另一种解决方案是将所有常量数据移动到基类并写入所有需要的 ctor,但它看起来很冗长。

有没有更简洁的实施方式?A(const A&, int a_)

C++ 构造 常量 复制构造函数 delegating-constructor

评论

0赞 StoryTeller - Unslander Monica 8/1/2017
值是不受约束的吗?a_
0赞 Sergey 8/1/2017
@StoryTeller你说的不受约束是什么意思? 并且不一定是整数,这只是一个示例。通常,构造函数接受对值的常量引用。aa_
1赞 systemcpro 8/1/2017
+1 的问题,因为我有过很多次,只是将所有内容转储到带有构造函数的嵌套结构中。然后,由于访问本来是我自己的成员现在有点丑陋,我把 getter 和 setter 放在主类上,并假装我自己和其他人都是 OO,以至于我什至不会在没有 getter 和 setter 的情况下访问我的 on 成员变量,并且真的一直打算把它们放在那里。我很想听听这里的 boffs 想出了什么。
0赞 Marius Bancila 8/1/2017
为什么不呢?int a_int const a_
0赞 Sergey 8/1/2017
@MariusBancila好吧,顺其自然。解决了我的问题。

答:

0赞 Tezirg 8/1/2017 #1

具有完整初始化列表的复制构造函数呢?由于您的数据是常量的,因此您只能使用初始化列表为其分配值。

A(const A& op, int a_) : 
  prop_a(op.prop_a_), 
  prop_b(op.prop_b_), 
  // continue for all members ...
  a(a_)  // except a
{
}

评论

3赞 Quentin 8/1/2017
我认为这是 OP 想要避免的(“避免手动初始化所有数据成员”),但这确实是唯一的解决方案。
2赞 Serge Ballesta 8/1/2017 #2

不幸的是,C++ const 字段初始化是一个非常特殊的情况,具有特定的语法,构造函数委派也是如此,并且构造函数语法没有提供混合它们,因此这里不可能有干净整洁的解决方案(至少对于当前的 C++ 版本,也许以后......我能想象到的最好的是:

class A
{
public:
        A() : a(1) {}
        A(const A& op):
             const_field1(op.const_field1),..., a(op.a) // all const fields here
           { init() };
        A(const A& op, int a_):
             const_field1(op.const_field1),..., a(a))   // dup line at editor level

private:
        void init(void) {
            // init non const fields here
        }
        // ... Lots of constant and non-constant member data ...
        const int a;
};

如果您只有复制 ctor 和一个额外的 ctor,则没有意义,但如果您有许多额外的 ctor,它可以简化代码维护。遗憾的是,只有非常量字段设置可以用私有方法在不同的 ctor 之间分解,但 C++ 标准就是这样。