Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sdd.hp.com!hplabs!hpcc01!hpcuhb!hpda!hpcupt1!thomasw From: thomasw@hpcupt1.HP.COM (Thomas Wang) Newsgroups: comp.lang.c++ Subject: Re: Failed constructors ( Was Re: Failed allocation in constructors? ) Message-ID: <7050025@hpcupt1.HP.COM> Date: 23 Jul 90 17:34:36 GMT References: <11061@alice.UUCP> Organization: Hewlett Packard, Cupertino Lines: 66 / hpcupt1:comp.lang.c++ / garry@alice.UUCP (garry hodgson) / 9:08 am Jul 18, 1990 / >"How do I deal with the case where a constructor fails?" Note that >this does not necessarily mean the memory allocation failed. Is there, >indeed, an elegant way to handle this? >An example from my own work: >I have a Connection class for doing IPC via sockets. What I'd like to do >is something like: > Connection *connection = new Connection( "kgbvax", PortNum ); > if ( connection ) > SendSecretDocuments( connection ); > else ComplainLoudly(); This semantic might not be too hot. The memory allocation success and the connection success are independent. Returning a null pointer will not allow you to put in information in the object that would explain why the connection fails. >Instead, what I do is: > Connection *connection = new Connection( "kgbvax", PortNum ); > if ( connection->status() == GoAhead ) > SendSecretDocuments( connection ); > else ComplainLoudly(); I think the best solution is using an exception handling mechanism. In the connection constructor, the construction failure would cause an exception to be raised. You can put information about the failure in the exception object. In this case, check for good connection is not necessary. Raising an exception without a handler would cause the 'explaination' member function of the exception to be invoked, then terminate the program. This is part of my exception handling mechanism: #define WHEREAMI __FILE__,__LINE__,me #define RAISE(msg,type,parm) new type (WHEREAMI,msg)->fail parm // usage: // RAISE("", no_memory_fail_t, ()); #define protect(var) { handler_t var; if (! setjmp(var.jump_buffer)) #define catcher(var, type) else if (var.can_handle(type ::id)) #define end_protect(var) else var.abort(); } // usage: // protect(var) // { // ... code which could cause some exception to be raised // } // catcher(var, no_memory_fail_t) // { // ... code which recovers from out of memory failure // } // catcher(var, all_fail_t) // { // .. code which recovers from generic failure // } // end_protect(var) -Thomas Wang (Everything is an object.) wang@hpdmsjlm.cup.hp.com thomasw@hpcupt1.cup.hp.com