你只要创建一个“混合风格”(mixin-style)的基类,这种基类允许子类继承它某一特定的功能——这里指的是建立一个类的new-handler的功能。之所以设计一个基类,是为了让所有的子类可以继承set_new_handler和operator new功能,而设计模板是为了使每个子类有不同的currenthandler数据成员。这听起来很复杂,不过你会看到代码其实很熟悉。区别只不过是它现在可以被任何类重用了。


template<class t> // 提供类set_new_handler支持的
class newhandlersupport { // 混合风格”的基类
public:
 static new_handler set_new_handler(new_handler p);
 static void * operator new(size_t size);

private:
 static new_handler currenthandler;
};

template<class t>
new_handler newhandlersupport<t>::set_new_handler(new_handler p)
{
 new_handler oldhandler = currenthandler;
 currenthandler = p;
 return oldhandler;
}

template<class t>
void * newhandlersupport<t>::operator new(size_t size)
{
 new_handler globalhandler =
  std::set_new_handler(currenthandler);
 void *memory;
 try {
  memory = ::operator new(size);
 }
 catch (std::bad_alloc&) {
  std::set_new_handler(globalhandler);
  throw;
 }
 
 std::set_new_handler(globalhandler);
 return memory;
}
// this sets each currenthandler to 0

template<class t>
new_handler newhandlersupport<t>::currenthandler;

有了这个模板类,对类x加上set_new_handler功能很简单了:只要让x从newhandlersupport<x>继承:
// note inheritance from mixin base class template. (see
// my article on counting objects for information on why
// private inheritance might be preferable here.)
class x: public newhandlersupport<x> {

...  // as before, but no declarations for
};  // set_new_handler or operator new
 


  使用x的时候依然不用理会它幕后在做些什么;老代码依然工作。这很好!那些你常不去理会的东西往往是可信赖的。

  使用set_new_handler是处理内存不够情况下一种方便,简单的方法。这比把每个new都包装在try模块里当然好多了。而且,newhandlersupport这样的模板使得向任何类增加一个特定的new-handler变得更简单。“混合风格”的继承不可避免地将话题引入到多继承上去,在转到这个话题前,你一定要先阅读条款43。

  1993年前,c++一直要求在内存分配失败时operator new要返回0,现在则是要求operator new抛出std::bad_alloc异常。很多c++程序是在编译器开始支持新规范前写的。c++标准委员会不想放弃那些已有的遵循返回0规范的代码,所以他们提供了另外形式的operator new以继续提供返回0功能。这些形式被称为“无抛出”,因为他们没用过一个throw,而是在使用new的入口点采用了nothrow对象:


class widget { ... };

widget *pw1 = new widget;// 分配失败抛出std::bad_alloc if

if (pw1 == 0) ... // 这个检查一定失败
 widget *pw2 = new (nothrow) widget;  // 若分配失败返回0
 
if (pw2 == 0) ... // 这个检查可能会成功
 


  不管是用“正规”(即抛出异常)形式的new还是“无抛出”形式的new,重要的是你必须为内存分配失败做好准备。简单的方法是使用set_new_handler,因为它对两种形式都有用。