FAQ 31.04 Should the object that manages a resource also perform operations that may throw exceptions?

Not usually.

In the following example, class Fred both manages a resource (an X allocation) and performs some operations that may throw exceptions (it calls the function mayThrow()). In other words, Fred violates the guideline. When Fred's constructor throws an exception (as a result of calling mayThrow()), there is a resource leak.

 #include <new> #include <iostream> using namespace std; class X { }; void mayThrow() throw(int)   { throw 42; } class Fred { public:   Fred() throw(bad_alloc, int);  ~Fred() throw();   Fred(const Fred& f) throw();   Fred& operator= (const Fred& f) throw(); private:   X* p_; }; Fred::Fred() throw(bad_alloc, int)   : p_(new X()) { mayThrow(); } Fred::~Fred() throw()   { cout << "Not reached #1\n"; delete p_; } int main() {   try {     Fred f;     cout << "Not reached #2\n";   }   catch (int e) {     cout << "Exception caught: " << e << "\n";   } } 

Because the guideline is violated, the X object leaks: the delete p_ instruction in Fred::~Fred() is never executed. Either Fred should focus on being a resource manager and nothing but a resource manager or Fred should delegate the resource management responsibility to some other class. In other words, either get rid of the code that calls mayThrow() from Fred, or change the X* to an auto_ptr<X>.

In those cases where it is not possible to abide by the discipline, a try block can be put in the constructor initialization list. Use this only as a last resort.



C++ FAQs
C Programming FAQs: Frequently Asked Questions
ISBN: 0201845199
EAN: 2147483647
Year: 2005
Pages: 566
Authors: Steve Summit

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net