Чтение онлайн

на главную - закладки

Жанры

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

Александреску Андрей

Шрифт:

class В { // ...

publiс:

 B* Clone const { // Невиртуальная функция

B* р = DoClone;

assert(typeid(*p) == typeid(*this) &&

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

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

Убедитесь, что ваш оператор присваивания безопасен в смысле присваивания самому себе. Избегайте написания оператора копирующего присваивания, который для корректной работы полагается на проверку присваивания самому себе; зачастую это говорит о недостаточной безопасности в смысле исключений. Если вы пишете копирующее присваивание с использованием идиомы обмена (см. рекомендацию 56), то вы автоматически обеспечиваете как строгую безопасность в смысле исключений, так и безопасность в смысле присваивания самому себе. Если присваивание самому себе часто встречается в программе из-за использования ссылочных синонимов или по каким-то иным причинам, проверка присваивания самому себе может использоваться в качестве средства оптимизации во избежание лишней работы.

Явно вызывайте все операторы присваивания базовых классов и всех данных-членов ([Meyers97] §16); обратите внимание, что идиома обмена автоматически заботится обо всех этих вещах. Возвращайте из оператора присваивания значение

*this
([Meyers97] §15).

Ссылки

[Alexandrescu03a] • [Cargill92] pp. 41-42, 95 • [Cline99] §24.01-12 • [Koenig97] §4 • [Meyers96] §33 • [Meyers97] §17 • [Murray93] §2.2.1 • [Stroustrup00] §10.4.4.1, §10.4.6.3 • [Sutter00] §13, §38, §41 • [Sutter04] §19

56. Обеспечьте бессбойную функцию обмена

Резюме

Обычно имеет смысл предоставить для класса функцию

swap
в целях эффективного и бессбойного обмена внутреннего содержимого объекта с внутренним содержимым другого объекта. Такая функция может пригодиться для реализации ряда идиом, от простого перемещения объектов до реализации присваивания, легко обеспечивающего функцию принятия результатов работы со строгими гарантиями безопасности для вызывающего кода (см. также рекомендацию 51).

Обсуждение

Обычно функция

swap
выглядит примерно следующим образом (здесь
U
— некоторый пользовательский тип):

class T { // ...

public:

 void swap(T& rhs) {

member1_.swap(rhs.member1_);

std::swap(member2_, rhs.member2_);

 }

private:

 U member1_;

 int member2_;

Поделиться:
Популярные книги

Сын Тишайшего

Яманов Александр
1. Царь Федя
Фантастика:
попаданцы
альтернативная история
фэнтези
5.20
рейтинг книги
Сын Тишайшего

"Искажающие реальность" Компиляция. Книги 1-14

Атаманов Михаил Александрович
Искажающие реальность
Фантастика:
боевая фантастика
космическая фантастика
киберпанк
рпг
5.00
рейтинг книги
Искажающие реальность Компиляция. Книги 1-14

Школа. Первый пояс

Игнатов Михаил Павлович
2. Путь
Фантастика:
фэнтези
7.67
рейтинг книги
Школа. Первый пояс

Невеста на откуп

Белецкая Наталья
2. Невеста на откуп
Фантастика:
фэнтези
5.83
рейтинг книги
Невеста на откуп

Убивать чтобы жить 2

Бор Жорж
2. УЧЖ
Фантастика:
героическая фантастика
боевая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 2

Вперед в прошлое!

Ратманов Денис
1. Вперед в прошлое
Фантастика:
попаданцы
5.00
рейтинг книги
Вперед в прошлое!

Аргумент барона Бронина 4

Ковальчук Олег Валентинович
4. Аргумент барона Бронина
Фантастика:
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Аргумент барона Бронина 4

Измена. (Не)любимая жена олигарха

Лаванда Марго
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. (Не)любимая жена олигарха

Измена. Право на обман

Арская Арина
2. Измены
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Право на обман

Бастард Императора. Том 7

Орлов Андрей Юрьевич
7. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 7

Жаба с кошельком

Донцова Дарья
19. Любительница частного сыска Даша Васильева
Детективы:
иронические детективы
8.26
рейтинг книги
Жаба с кошельком

Бастард Императора. Том 11

Орлов Андрей Юрьевич
11. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 11

Академия чаросвет. Тень

Ярошинская Ольга
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Академия чаросвет. Тень

Наследие Маозари 4

Панежин Евгений
4. Наследие Маозари
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Наследие Маозари 4