在用户定义复制构造函数中隐式复制构造函数的使用

Use of the Implicit Copy Constructor in User-Defined Copy Constructor

本文关键字:复制 构造函数 用户 定义      更新时间:2023-10-16

我有一个相当大且冗长的类,其中隐式生成的复制构造函数几乎完全正确,除了一个特定的字段。

是否有一种方法可以编写用户定义的复制构造函数,调用隐式版本,然后在末尾添加一或两行?或者我必须编写一个冗长的、(而且无聊的、容易输入错误的)用户定义的复制构造函数,它主要重复隐式的复制构造函数?

class MySimpleObject
{
private:
   FieldA m_fieldA;
   FieldB m_fieldB;
   [... repeated a lot...]
   SpecialField m_trickyField;
public:
    MySimpleObject(const MySimpleObject& other)
    {
        ImplicitCopyCtor(*this,other); // This is what I want to simplify, instead of copying all the fields by hand.
        m_trickyField.DoCloneSeparately(other.m_trickyField);
    }
};

注意: SpecialField是由第三方库提供的,所以我不能重构或修改它。我不知道为什么不能正确地复制,但是它不能,我认为有一个很好的理由。我喜欢将它包装在一个行为正常的类中的想法。我来查一下。

软件工程的基本定理是你的朋友:

struct MakeSpecialSnowflakeLessSpecial
{
  MakeSpecialSnowflakeLessSpecial(const MakeSpecialSnowflakeLessSpecial& other)
  {
    m_trickyField.DoCloneSeparately(other.m_trickyField);
  }
  SpecialField m_trickyField;
};

class MySimpleObject
{
private:
   FieldA m_fieldA;
   FieldB m_fieldB;
   [... repeated a lot...]
   MakeSpecialSnowflakeLessSpecial m_special;
public:
    MySimpleObject(const MySimpleObject&) = default;
};

不,没有。

最好的办法是修复有问题的成员。

一个快速的解决方案可能是将其包装在一个类中,以保持其复制语义。

我能想到有两种方法来解决你的问题:

  1. 把正常的东西放在一个额外的结构体中,你从private继承。
  2. 将需要特殊处理的字段类型包装到另一个类型中,以便在那里实现所需的复制语义。

第一个解决方案是这样的:

struct MySimpleObjectDefaultData
{
    FieldA m_fieldA;
    FieldB m_fieldB;
   // [... repeated a lot...]
}
class MySimpleObject : private MySimpleObjectDefaultData
{
private:
   SpecialField m_trickyField;
public:
    MySimpleObject(const MySimpleObject& other)
        : MySimpleObjectDefaultData( other )
    {
        m_trickyField.DoCloneSeparately(other.m_trickyField);
    }
};

这对于代码的其余部分来说侵入性较小,因为访问权限和字段的类型保持完全相同。要使此解决方案工作,您不需要触及现有代码的其余部分。此外,这个解决方案更通用一些,因为实际上可以手动将任何后处理步骤应用于编译器生成的复制构造函数。

第二个是这样的:

struct SpecialFieldWrapper : SpecialField
{
    using SpecialField::SpecialField;
    SpecialFieldWrapper( const SpecialFieldWrapper & other )
    {
        DoCloneSeparately( other.m_trickyField );
    }
};
class MySimpleObject
{
private:
   FieldA m_fieldA;
   FieldB m_fieldB;
   [... repeated a lot...]
   SpecialFieldWrapper m_trickyField;
public:
    MySimpleObject(const MySimpleObject& other)
    {
        ImplicitCopyCtor(*this,other); // This is what I want to simplify, instead of copying all the fields by hand.
        m_trickyField.DoCloneSeparately(other.m_trickyField);
    }
};

这个解决方案可能比第一个更容易阅读。但是,类型会发生轻微变化,这可能需要对代码进行进一步更改。