Обеспечение правильного обслуживания Clone () в C ++ - PullRequest
1 голос
/ 02 июля 2010

В C ++ я считаю очень полезным добавить метод «Clone ()» к классам, которые являются частью иерархий, требующих (особенно полиморфного) дублирования с такой подписью:

class Foo {
public:
virtual Foo* Clone() const;
};

Это можетвыглядят симпатично, но это очень склонно к ошибкам, внесенным обслуживанием класса.Всякий раз, когда кто-либо добавляет элемент данных в этот класс, он должен помнить, чтобы обновить метод Clone ().Неудача приводит к часто неуловимым ошибкам.Модульные тесты не найдут ошибку, если они не будут обновлены или класс не имеет метод сравнения на равенство, который является модульным тестом и обновлен для сравнения нового члена.Сопровождающие не получат ошибку компилятора.Метод Clone () выглядит универсальным и его легко пропустить.

У кого-нибудь еще есть проблемы с Clone () по этой причине?Я склонен помещать комментарий в заголовочный файл класса, напоминая сопровождающим обновлять Clone, если они добавляют членов данных.Есть ли идея получше?Было бы глупо / педантично вставить #, если / etc.директивы искать изменение размера класса и сообщать о предупреждении / ошибке?

Ответы [ 2 ]

4 голосов
/ 02 июля 2010

Почему бы просто не использовать конструктор копирования?

virtual Foo* Clone() const { return new Foo(*this); }

Редактировать: Ой, подождите, класс Foo - BASE, а не класс DERIVED?Тот же принцип.

virtual Foo* Clone() const { return new MyFavouriteDerived(*this); }

Просто убедитесь, что все производные классы реализуют клон таким образом, и у вас не будет проблем.Конструктор личных копий не является проблемой, поскольку метод является членом и, следовательно, может получить к нему доступ.

1 голос
/ 02 июля 2010

Хорошо, этот вопрос меня смутил. Сначала я думал, что вы хотите автоматически создать clone (), и я собирался направить вас к обсуждению , которое я провел пару лет назад .

Однако ... это не похоже на то, что вы хотите. Поэтому я просто рассмотрю ваши предположения:

Всякий раз, когда кто-либо добавляет элемент данных в этот класс, он должен помнить об обновлении метода Clone ().

Почему ?? Конечно, вы реализовали clone () в терминах конструктора копирования.

struct X { X* clone() const { return new X(*this); } };

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

Это не должно быть проблемой, поскольку вы наверняка обновили модульный тест ПЕРЕД добавлением члена ...

У кого-нибудь еще есть проблема с Clone () по этой причине?

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

...