(Click here, next to the previous article)
However, you may still be worried about inheriting widgets from newhandlersupport <widget>. If so, when you notice that the newhandlersupport template never uses its type parameter T, you may be more worried. It does not need to do that. All we need is to provide a copy of different newhandlersupport-especially its static data member (static data member) currenthandler-for each class inherited from newhandlersupport. Template parameter T is only used to distinguish an inheriting class from another one. The template mechanism automatically generates a copy of currenthandler for T in each instantiated newhandlersupport.
Widgets inherit from a templatized base class (templated base class) that treats widgets as a type parameter (type parameter). If this concept makes you confused, you don't have to worry about it. It initially has this impact on everyone. However, it evolved into a useful technology with a name, although it does not seem to reflect the fact that they saw it for the first time. It is calledCuriously recurring template Pattern(Peculiar recursive template mode) (crtp ). True.
In this regard, I have published an article suggesting a better name: "Do It For Me", because when widgets inherit from newhandlersupport <widget>, it is actually saying: "I am a widget, And I want to inherit from the newhandlersupport class for the widget." No one uses my proposed name (or even myself), but one way to consider crtp as "Do It For Me" may help you understand templatized inheritance (templated inheritance) what are you doing.
Templates such as newhandlersupport make it easy to add a class-specific new-handler for any class in need. However, Mixin-style inheritance always leads to the thread of multiple inheritance (Multi-inheritance), and you need to read item 40 before we proceed along this path.
Until 1993, C ++ required operator new not to allocate the requested memory to return null. Operator new is now specified to throw a bad_alloc exception, but many c ++ programs are written before the compiler starts to support this revision standard. The C ++ Standardization Committee does not want to discard the code Basics of the test-for-null (check whether it is null), so they provide an alternative form of operator new, it is used to provide the traditional act of failure-yields-null (failure leads to null. These forms are called "nothrow", which is partly because they use nothrow objects (defined in header file <New>) where new is used ):
Class widget {...};
Widget * pw1 = new widget; // throws bad_alloc if
// Allocation fails
If (pw1 = 0)... // This test must fail
Widget * pw2 = new(STD: nothrow)Widget; // returns 0 if allocation
// The widget fails
If (pw2 = 0)... // This test may succeed
For exceptions, nothrow new provides less mandatory assurance than originally looked. In the expression "New (STD: nothrow) widget", two things occur. First, operator new's nothrow version is called to allocate enough memory for a widget object. If the allocation fails, operator new returns NULL pointer. However, if it succeeds, the widget constructor is called, and at this moment, all the gambling bets are invalid. Widget constructor can do anything it wants. It may have new memory, but if it does, it is not forced to use nothrow new. So, although operator new called in "New (STD: nothrow) widget" won't be thrown, widget constructor can. If it does, the exception is propagated as usual. Conclusion? The use of nothrow new can only ensure that operator new will not throw, but cannot guarantee that an expression like "New (STD: nothrow) widget" will never cause an exception. Among all possibilities, you 'd better never need nothrow new.
Whether you are using "normal" (that is, exception-throwing) new or a little short, it is very important to understand the behavior of New-handler, because it can be used in two forms.
Things to remember
- Set_new_handler allows you to specify a function that can be called when the memory allocation request cannot be satisfied.
- Nothrow new is limited because it applies only to memory allocation, and subsequent constructor calls may still throw exceptions.