Стандарты программирования на С++. 101 правило и рекомендация | страница 95



>   "DoClone incorrectly overridden");

>  return p; // проверка типа, возвращаемого DoClone

> }

>protected:

> B(const B&);

>private:

> virtual B* DoClone() const = 0;

>};

Функция >Clone теперь является невиртуальным интерфейсом, используемым вызывающим кодом. Производные классы должны перекрыть функцию >DoClone. Дополнительная проверка обнаружит все копии, которые имеют тип, отличный от оригинала, тем самым оповещая, что в некотором производном классе не перекрыта функция >DoClone; в конце концов, задача >assert состоит именно в обнаружении и сообщении о таких программных ошибках (см. рекомендации 68 и 70).

Исключения

Некоторые проектные решения могут требовать, чтобы копирующие конструкторы базовых классов оставались открытыми (например, когда часть вашей иерархии представляет собой библиотеку стороннего производителя). В таком случае следует предпочесть передачу посредством (интеллектуального) указателя передаче по ссылке; как показано в рекомендации 25, передача посредством указателя существенно менее подвержена срезке и нежелательному созданию временных объектов.

Ссылки

[Dewhurst03] §30, §76, §94 • [Meyers96] §13 • [Meyers97] §22 • [Stroustrup94] §11.4.4 • [Stroustrup00] §12.2.3

55. Предпочитайте канонический вид присваивания

Резюме

При реализации оператора >operator= предпочитайте использовать канонический вид — невиртуальный с определенной сигнатурой.

Обсуждение

Предпочтительно объявлять копирующее присваивание для типа >T с одной из следующих сигнатур (см. [Stroustrup00] и [Alexandrescu03a]):

>T& operator=(const T&); // классический вид

>T& operator=(T);        // потенциально оптимизированный

>                        // вид (см. рекомендацию 27)

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

Избегайте делать любой оператор присваивания виртуальным (см. [Meyers96] §33 и [Sutter04] §19). Если вы полагаете, что вам требуется виртуальное поведение присваивания, обратитесь сначала к указанной литературе. Если и после этого вы стоите на своем, то лучше использовать виртуальную именованную функцию, а не оператор (например, >virtual void Assign(const T&);).

He возвращайте >const T&. Хотя этот тип возвращаемого значения имеет то преимущество, что защищает от странных присваиваний наподобие >(a=b)=c, главным его недостатком является то, что вы не сможете поместить объекты типа