C++ : Debugging and error handling


PART 9

Q39: How can I handle a constructor that fails?
A: Constructors (ctors) do not return any values, so no returned error code
is possible.  There are many possibilities for how to handle this, one of
which is to set the object itself into a `half baked' state by setting an
internal status bit.  Naturally there should be a query (`inspector') method
to check this bit, allowing clients to discover whether they have a live
object.  Other member functions should check this bit, and either do a no-op
(or perhaps something more obnoxious such as `abort()') if the object isn't
really alive.  Check out how the iostreams package handles attempts to open
nonexistent/illegal files for an example of prior art.

One more thing: you might want to store information indicating *why* the
failure took place in addition to a `failure bit'.

When real exceptions come to C++, they will provide a better strategy; the best
technique will generally be to throw an exception.



Q40: How can I compile-out my debugging print statements?
A: This will NOT work, since comments are parsed before the macro is expanded:
	#ifdef DEBUG_ON
	  #define  DBG
	#else
	  #define  DBG  //
	#endif
	DBG cout << foo;

This is the simplest technique:
	#ifdef DEBUG_ON
	  #define  DBG(anything)  anything
	#else
	  #define  DBG(anything)  /*nothing*/
	#endif

Then you can say:
	//...
	DBG(cout << "the value of foo is " << foo << '\n');
	//                                                ^-- `;' outside ()

Any commas in your `DBG()' statement must be enclosed in a `()':
	DBG(i=3, j=4);	//<---- C-preprocessor will generate error message
	DBG(i=3; j=4);	//<---- ok

There are also more complicated techniques that use variable argument lists,
but these are primarily useful for `printf()' style (see question on the pros
and cons of  as opposed to  for more).