【问题标题】:Delegating copy constructor and const data initialization委托复制构造函数和常量数据初始化
【发布时间】:2018-01-08 00:42:32
【问题描述】:

我有一个类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_);

这里应该复制op,之后应该用a_ 初始化a,或者不要复制。我想通过委托给复制构造函数来避免手动初始化所​​有数据成员,但是在这种情况下如何覆盖我的 const 数据成员? 例如:

// 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&amp;, int a_)

【问题讨论】:

  • a_的值是否不受约束?
  • @StoryTeller 你所说的不受约束是什么意思? aa_ 不一定是整数,这只是一个例子。通常,构造函数接受对值的 const 引用。
  • +1 有问题,因为我已经有很多次了,只是将所有内容都转储到带有构造函数的嵌套结构中。然后,由于访问本来是我自己的成员的东西现在有点难看,我将 getter 和 setter 放在主类上,并向自己和其他人假装我太OO了,我什至不会访问我的成员变量getter 和 setter,并且真的一直打算把它们放在那里。很想听听这里的朋友们想出什么。
  • 为什么int a_ 不是int const a_
  • @MariusBancila 好的,顺其自然。解决了我的问题。

标签: c++ constructor constants copy-constructor delegating-constructor


【解决方案1】:

不幸的是,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,它可以简化代码的可维护性。遗憾的是,只有非常量的字段设置才能通过私有方法在不同的ctors之间进行因式分解,但C++标准就是这样。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 我认为这是 OP 想要避免的(“避免手动初始化所​​有数据成员”),但这确实是唯一的解决方案。
    猜你喜欢
    • 2012-11-15
    • 2020-12-27
    • 1970-01-01
    • 2020-06-13
    • 2012-08-24
    • 1970-01-01
    • 2013-01-29
    • 1970-01-01
    • 2016-10-02
    相关资源
    最近更新 更多