46. При наличии пользовательского new следует предоставлять все стандартные типы этого оператора

46. При наличии пользовательского new следует предоставлять все стандартные типы этого оператора

Резюме

Если класс определяет любую перегрузку оператора new, он должен перегрузить все три стандартных типа этого оператора — обычный new, размещающий и не генерирующий исключений. Если этого не сделать, то эти операторы окажутся скрытыми и недоступными пользователям вашего класса.

Обсуждение

Обычно пользовательские операторы new и delete нужны очень редко, но если они все же оказываются необходимы, то вряд ли вы захотите, чтобы они скрывали встроенные сигнатуры.

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

Пусть вы определили следующий оператор new, специфичный для класса:

class С {

 // ...

 // Скрывает три стандартных вида оператора new

 static void* operator new(size_t, MemoryPool&);

};

Теперь, если кто-то попытается написать выражение с обычным стандартным new С, компилятор сообщит о том, что он не в состоянии найти обычный старый оператор new. Объявление перегрузки C::operator new с параметром типа MemoryPool скрывает все остальные перегрузки, включая знакомые встроенные глобальные версии, которые все мы знаем и любим:

void* operator new(std::size_t); // Обычный

void* operator new(std::size_t,

 std::nothrow_t) throw();        // He генерирующий исключений

void* operator new(std::size_t,

 void*);                         // Размещающий

В качестве другого варианта событий предположим, что ваш класс предоставляет некоторую специфичную для данного класса версию оператора new — одну из трех. В таком случае это объявление также скроет остальные две версии:

class С {

 // ...

 // Скрывает две другие стандартные версии оператора new

 static void* operator new(size_t, void*);

};

Предпочтительно, чтобы у класса С в его область видимости были явно внесены все три стандартные версии оператора new. Обычно все они должны иметь одну и ту же видимость. (Видимость для отдельных версий может быть сделана закрытой, если вы хотите явно запретить один из вариантов оператора new, однако цель данной рекомендации — напомнить, чтобы вы не скрыли эти версии непреднамеренно.)

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

Все, что осталось упомянуть, — это то, что внесение оператора new в область видимости может быть сделано двумя различными способами в двух разных ситуациях. Если базовый класс вашего класса также определяет оператор new, все, что вам надо, — "раскрыть" оператор new:

class С : public B { // ...

public:

 using B::operator new;

};

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

class C { // ...

public:

 static void* operator new(std::size_t s) {

  return ::operator new(s);

 }

 static void* operator new(std::size_t s,

  std::nothrow_t nt) throw() {

  return ::operator new(s, nt);

 }

 static void* operator new(std::size_t s, void* p) {

  return ::operator new(s, p);

 }

};

Рассмотренная рекомендация применима также к версиям операторов для массивов — operator new[].

Избегайте вызова версии new(nothrow) в вашем коде, но тем не менее обеспечьте и ее, чтобы пользователи вашего класса не оказались в какой-то момент неприятно удивлены.

Ссылки

[Dewhurst03] §60 • [Sutter04] §22-23

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг:

23.2.1. Стандартные типы данных библиотеки Glib

Из книги автора

23.2.1. Стандартные типы данных библиотеки Glib Библиотека Glib содержит типы данных, аналогичные типам данных языка С, а также такие структуры, как деревья, списки; функции для работы с памятью и обработки ошибок. Это сделано для того, чтобы ваше приложение могло быть легко


Стандартные типы данных и описание переменных

Из книги автора

Стандартные типы данных и описание переменных Значение присваиваемое переменной должно соответствовать её типу указанному в разделе описаний. В Pascal есть четыре стандартных типа величин (помимо тех, что могут быть дополнительно определены в каждой программе –


Стандартные типы данных и описание переменных

Из книги автора

Стандартные типы данных и описание переменных int – целоеlong – длинное целоеshort – короткое целоеunsigned – беззнаковое целоеfloat – вещественноеdouble – длинное вещественноеchar – литерноеВ отличии от Pfscal, в С логических переменных нет.Примеры описания переменных:int k;char a,


Пример: блокировка на чтение при наличии в очереди блокировки на запись

Из книги автора

Пример: блокировка на чтение при наличии в очереди блокировки на запись Первый вопрос, на который мы попытаемся найти ответ, звучит так: если ресурс заблокирован на чтение и какой-то процесс послал запрос на установление блокировки на запись, будет ли при этом разрешена


Отмена права предоставлять привилегии

Из книги автора

Отмена права предоставлять привилегии Для отмены права у пользователя предоставлять конкретную привилегию, но сохранить у него эту привилегию, используйте REVOKE GRANT OPTION:REVOKE GRANT OPTIONFOR <привилегия> [, <привилегия> [,...]]ON <таблица> | <объект>FROM <пользователь>


Стандартные типы

Из книги автора

Стандартные типы Общие типы shortstring = string[255] Тип короткой размерной строки DateTime Тип даты и времени Tuple Тип кортежа StringBuilder Тип изменяемой строки символов Encoding Тип кодировки символов TextFile Синоним типа


Стандартные процедурные типы

Из книги автора

Стандартные процедурные типы Action0 Представляет действие без параметров Action<T> Представляет действие с одним параметром Action2<T1,T2> Представляет действие с двумя параметрами Action3<T1,T2,T3> Представляет действие с тремя параметрами Func0<Res>


Анатолий Вассерман: После этого не значит вследствие этого Анатолий Вассерман

Из книги автора

Анатолий Вассерман: После этого не значит вследствие этого Анатолий Вассерман Опубликовано 19 мая 2010 года Выпуск 215 Анатолий Вассерман вновь возвращается к теме сталинской эпохи и репрессий. На этот раз он опровергает мнение о том, что


Глава 8 Стандартные приложения Windows, о которых следует знать

Из книги автора

Глава 8 Стандартные приложения Windows, о которых следует знать В состав Windows входит много стандартных программ. Все их можно найти в меню Пуск, Программы, Стандартные. Программы в этой программной группе очень просты в использовании, поэтому нет особой необходимости


Отправка с сайта оператора

Из книги автора

Отправка с сайта оператора На сегодняшний день уже, наверное, все операторы поддерживают отправку SMS со своего сайта. Сообщения, правда, можно отправить только абонентам данного оператора, но этого, как правило, бывает достаточно.Итак, к практике. Сейчас мы рассмотрим


Предоставлять отчеты вышестоящему руководству

Из книги автора

Предоставлять отчеты вышестоящему руководству Недавно я беседовала с генеральным директором большой промышленной компании о вопросах безопасности. Она захотела разобраться, как ей узнать о наличии риска для ее сети.Я задала ей следующие вопросы:1. Получали ли вы


Как мы дошли до этого

Из книги автора

Как мы дошли до этого Если вы хотите обвинить кого-то в компьютеризации Америки, предъявите свои претензии Джорджу Вашингтону и другим авторам конституции. В 1787 году Вашингтон с единомышленниками объявил, что новая республика должна проводить перепись населения каждые