Вопрос:

Использование конструктора неявного копирования в определяемом пользователем конструкторе копирования

c++ copy-constructor

404 просмотра

3 ответа

49499 Репутация автора

У меня есть довольно большой и длинный класс, в котором неявно сгенерированный конструктор копирования будет делать почти все правильно, за исключением одного конкретного поля.

Есть ли способ написать пользовательский конструктор копирования, который вызывает неявную версию, а затем добавляет одну или две строки в конце? Или мне нужно написать длинный (и скучный, и склонный к опечаткам) определяемый пользователем конструктор копирования, который в основном дублирует неявный?

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 предоставляется сторонней библиотекой, поэтому я не могу изменить ее или изменить. Я не знаю, почему это не копирует должным образом, но это не так, и я предполагаю, что есть веская причина. Мне нравится идея оборачивать его в класс, который будет вести себя правильно. Я посмотрю на это.

Автор: abelenky Источник Размещён: 22.08.2016 09:50

Ответы (3)


4 плюса

320023 Репутация автора

Нет, нет

Ваш лучший выбор - исправить проблемного участника.

Быстрое решение может заключаться в том, чтобы обернуть его в класс, который нарушает семантику копирования.

Автор: Lightness Races with Monica Размещён: 22.08.2016 09:54

17 плюса

139796 Репутация автора

Фундаментальная теорема программной инженерии является вашим другом:

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;
};
Автор: Jonathan Wakely Размещён: 22.08.2016 09:57

2 плюса

14690 Репутация автора

Есть два решения вашей проблемы, о которых я могу подумать:

  1. Поместите обычный материал в дополнительную структуру, которую вы унаследуете от частного лица.
  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);
    }
};

Это решение может быть легче читать, чем первое. Однако типы меняются незначительно, и это может привести к дальнейшим изменениям в вашем коде.

Автор: Ralph Tandetzky Размещён: 23.08.2016 07:15
Вопросы из категории :
32x32