std::new_handler
NewHandlerSupport
{
std::new_handler oldHandler = currentHandler;
currentHandler = p;
return oldHandler;
}
template
void *NewHandlerSupport
throw(std::bad_alloc)
{
NewHandlerHolder h(std::set_new_handler(currentHandler);
return ::operator new(size);
}
// currentHandler в любом классе инициализируется значением null
template
std::new_handler NewHandlerSupport
С этим шаблоном класса добавление поддержки set_new_handler к Widget очень просто: Widget просто наследуется от NewHandlerSupport
class Widget: public NewHandlerSupport
... // как раньше, но без декларации
}; // set_new_handler или operator new
Это все, что нужно сделать в классе Widget, чтобы предоставить специфичный для класса обработчик set_new_handler.
Но может быть, вас беспокоит тот факт, что Widget наследует классу New-HandlerSupport
А что касается того, что Widget наследует шаблонному базовому классу, который принимает Widget как параметр типа, не пугайтесь, это только поначалу кажется непривычным. На практике это очень удобная техника, имеющая собственное название, которое отражает тот факт, что никому из тех, кто видит ее в первый раз, она не кажется естественной. А называется она
Однажды я опубликовал статью, в которой писал, что лучше было бы это назвать ее «Сделай Это Для Меня», потому что Widget наследует NewHandler-Support
Шаблоны, подобные NewHandlerSupport, упрощают добавление специфичных для класса обработчиков new к любому классу, которому это нужно. Однако наследование присоединяемому классу приводит к множественному наследованию, и прежде чем вставать на этот путь, вам, возможно, стоит перечитать правило 40.
До 1993 года C++ требовал, чтобы оператор new возвращал нулевой указатель, если не мог выделить нужную память. Теперь же operator new в этом случае должен возбуждать исключение bad_alloc. Но огромный объем кода на C++ был написан до того, как компиляторы стали поддерживать новую спецификацию. Комитет по стандартизации C++ не хотел отметать весь код, основанный на сравнении с null, поэтому было решено предоставить альтернативные формы operator new, обеспечивающие традиционное поведение с возвращением null при неудаче. Эти формы известны под названием «nothrow» (не возбуждающие исключений), потому что в них используются объекты nothrow (определенные в заголовке
class Widget {...};