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

跟風遠走 提交于 2019-12-14 00:50:19

问题


I have a rather large and lengthy class where the implicitly generated copy-constructor would almost do exactly the right thing, except for one specific field.

Is there a way to write a user-defined copy-constructor that calls the implicit version, and then adds one or two lines at the end? Or do I have to write a lengthy, (and boring, and typo-prone) user-defined copy-constructor that mostly duplicates the implicit one?

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

Note: SpecialField is provided by a 3rd party library, so I cannot refactor it or modify it. I don't know why it doesn't copy properly, but it doesn't, and I assume there's a good reason. I like the idea of wrapping it inside a class that will behave properly. I'll look into that.


回答1:


The fundamental theorem of software engineering is your friend:

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



回答2:


No, there is not.

Your best bet is to fix the problematic member.

A quick solution might be to wrap it in a class that unbreaks its copy semantics.




回答3:


There are two solutions to your problem, that I can think of:

  1. Put the normal stuff into an extra struct that you inherit from privately.
  2. Wrap the type of your field, that needs special treatment into an other type to implement the required copy-semantics there.

The first solution would look like this:

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

This is less invasive for the rest of your code, since the access rights and the types of the fields stay exactly the same. You will not need to touch the rest of your existing code, to make this solution work. Also, this solution is a bit more generic, since you can actually apply any post-processing steps to the compiler-generated copy constructor manually.

The second would look like this:

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

This solution may be easier to read than the first. However, types change slightly and this can make further changes to your code necessary.



来源:https://stackoverflow.com/questions/39089263/use-of-the-implicit-copy-constructor-in-user-defined-copy-constructor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!