Функция Clone
DoClone. Дополнительная проверка обнаружит все копии, которые имеют тип, отличный от оригинала, тем самым оповещая, что в некотором производном классе не перекрыта функция DoClone; в конце концов, задача assert состоит именно в обнаружении и сообщении о таких программных ошибках (см. рекомендации 68 и 70).Некоторые проектные решения могут требовать, чтобы копирующие конструкторы базовых классов оставались открытыми (например, когда часть вашей иерархии представляет собой библиотеку стороннего производителя). В таком случае следует предпочесть передачу посредством (интеллектуального) указателя передаче по ссылке; как показано в рекомендации 25, передача посредством указателя существенно менее подвержена срезке и нежелательному созданию временных объектов.
55. Предпочитайте канонический вид присваивания
При реализации оператора operator=
Предпочтительно объявлять копирующее присваивание для типа T
T& operator=(const T&); // классический вид
T& operator=(T); // потенциально оптимизированный
// вид (см. рекомендацию 27)
Второй вариант имеет смысл использовать, если вам в любом случае требуется копия аргумента в теле вашего оператора, как, например, при использовании идиомы, основанной на использовании функции обмена (см. рекомендацию 56).
Избегайте делать любой оператор присваивания виртуальным (см. [Meyers96] §33 и [Sutter04] §19). Если вы полагаете, что вам требуется виртуальное поведение присваивания, обратитесь сначала к указанной литературе. Если и после этого вы стоите на своем, то лучше использовать виртуальную именованную функцию, а не оператор (например, virtual void Assign(const T&);
He возвращайте const T&
(a=b)=c, главным его недостатком является то, что вы не сможете поместить объекты типа T в контейнеры стандартной библиотеки; эти контейнеры требуют, чтобы оператор присваивания возвращал тип T&.Всегда делайте копирующее присваивание безопасным в смысле исключений, причем предпочтительна строгая гарантия (см. рекомендацию 71).
Убедитесь, что ваш оператор присваивания безопасен в смысле присваивания самому себе. Избегайте написания оператора копирующего присваивания, который для корректной работы полагается на проверку присваивания самому себе; зачастую это говорит о недостаточной безопасности в смысле исключений. Если вы пишете копирующее присваивание с использованием идиомы обмена (см. рекомендацию 56), то вы автоматически обеспечиваете как строгую безопасность в смысле исключений, так и безопасность в смысле присваивания самому себе. Если присваивание самому себе часто встречается в программе из-за использования ссылочных синонимов или по каким-то иным причинам, проверка присваивания самому себе может использоваться в качестве средства оптимизации во избежание лишней работы.
Явно вызывайте все операторы присваивания базовых классов и всех данных-членов ([Meyers97] §16); обратите внимание, что идиома обмена автоматически заботится обо всех этих вещах. Возвращайте из оператора присваивания значение *this
56. Обеспечьте бессбойную функцию обмена
Обычно имеет смысл предоставить для класса функцию swap
Обычно функция swap
U — некоторый пользовательский тип):class T { // ...
public: