Вход/Регистрация
Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ
вернуться

Майерс Скотт

Шрифт:

class Base {

public:

...

static void *operator new(std::size_t size, // скрывает обычные

std::ostream& logStream) // глобальные формы

throw(std::bad_alloc);

...

};

Base *pb = new Base; // ошибка! Обычная форма

// оператора new скрыта

Base *pb = new (std::cerr)Base; // правильно, вызывается

// размещающий new из Base

Аналогично оператор new в производных классах скрывает и глобальную, и унаследованную версии оператора new:

class Derived: public Base {

public:

...

static void *operator new(std::size_t size) // переопределяет

throw(std::bad_alloc); // обычную форму new

...

};

Derived *pd = new (std::cerr)Derived; // ошибка! заменяющая

// форма теперь скрыта

Derived *pd = new Derived; // правильно, вызывается

// оператор new из Derived

В правиле 33 достаточно подробно рассмотрен этот вид сокрытия имен в классе, но при написании функций распределения памяти нужно помнить, что по умолчанию C++ представляет следующие формы оператора new в глобальной области видимости:

void operator new(std::size_t) throw(bad_alloc); // обычный new

void operator new(std::size_t, void*) throw(bad_alloc); // размещающий new

void operator new(std::size_t, // new, не возбуждающий

const std::nothrow_t&) throw; // исключений –

// см. правило 49

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

Самый простой способ – создать базовый класс, содержащий все нормальные формы new и delete:

class StandardNewDeleteForms {

public:

// нормальные new/delete

static void *operator new(std::size_t size) throw(bad_alloc)

{ return ::operator new(size);}

static void operator delete(void *pMemory) throw

{ ::operator delete(pMemory);}

// размещающие new/delete

static void *operator new(std::size_t size, void *ptr) throw(bad_alloc)

{ return ::operator new(size, ptr);}

static void operator delete(void *pMemory, void *ptr) throw

{ ::operator delete(pMemory, ptr);}

// не возбуждающие исключений new/delete

static void *operator new(std::size_t, const std::nothrow_t& nt) throw

{ return ::operator new(size, nt)}

static void operator delete(void *pMemory, const std::nothrow_t&) throw

{ ::operator delete(pMemory, nt);}

};

Пользователи, которые хотят пополнить свой арсенал специальными формами new, применяют наследование и using-объявления (см. правило 33), чтобы получить доступ к стандартным формам:

class Widget: public StandardNewDeleteForms { // наследование

public: // стандартных форм

using StandardNewDeleteForms::operator new; // сделать эти формы

using StandardNewDeleteForms::operator delete; // видимыми

static void *operator new(std::size_t size, // добавляется

std::ostream& logStream) // специальный

throw(bad_alloc); // размещающий new

static void operator delete(void *pMemory, // добавляется

std::ostream& logStream) // соответствующий

throw; // размещающий delete

...

};

  • Читать дальше
  • 1
  • ...
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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