[comp.lang.c++] How can I report an error when constructor parameters are wrong.

ev@chorus.fr (Eric Valette) (03/25/91)

/*
 *
 *	I would like to have opinions about the best way to check constructor
 *	parameters validity and report error to caller: I think that something
 *	is missing in the way you can report error to user using Cfront 2.0
 *	
 *	I order to introduce the problem, you can read the small following
 *	example. If I'm missing something let me know...
 */
			C++ example
//----------------------------------------------------------------------
#include <stdio.h>

class born_meter {
	
	int lowBound;
	int highBound;
	int curValue;
public:
	born_meter(int, int, int);
	~born_meter() {}
};

born_meter:: born_meter(int low, int high, int cur ) {
	
	if ( cur < low || cur > high || low > high ) {
		printf("bad initial values\n");
		delete this;	// must release memory already allocated
		return;
	}
	else {
		lowBound   = low;
		highBound = high;
		curValue = cur;
	}
		
	
}


main () {
	
	born_meter * ex1;
	born_meter * ex2;
	
	if ( (ex1 = new born_meter (1,10,5) ) == NULL) { // should work if I
		printf("allocation error\n");		 // I can get memory
	}

	if ( (ex2 = new born_meter (1,5,10) ) == NULL) { // sould produce an error
			printf("allocation error\n");    // that the user can get
	}

}

//--------------------------------------------------------------------

/* 				PROBLEM
 *				-------
 *	
 * Using a Cfront 2.0 compiler I get the "bad initial values" message
 * but not the "allocation error" message because I CAN'T RETURN NULL
 * IN THE CONSTRUCTOR (I cannot set a return value if I don't want to 
 * assign this (might be forbidden in the future release, do not want
 * to always write my own allocator) and "delete this" do not set this 
 * to zero).
 *
 * I Have already imagine some solutions :
 * ---------------------------------------
 *	
 * 1) I can create a new operator that check the parameter validity before
 * calling the global new operator.
 *	
 * 2) I can add a new parameter to the constructor and check the value
 * after the call.
 *	
 * They all have some draw back
 * ----------------------------
 *	
 * Problem with 1)
 * 
 *	- I must pass the parameter to the new operator AND the constructor
 *	- You cannot apply this solution to all the cases (sometimes it is
 *	not possible to do all the check in the new operator).
 *	- I must supply an operator delete if I want no warning.
 *
 *	
 * Problem with 2)
 * 
 *	- I must alway check the return value for new AND the value of
 *	the error flag (if global new operator returns null, the variable
 *	will not be set). I could also initialize this flag with an allocation
 *	error flag.
 *	- must add this error flag in all constructors.
 *	- memory will be allocated and then destroyed
 */
 
 
/* any better idea or comment would be appreciated.


   __                 
  /  `                   	Eric Valette
 /--   __  o _.          	Chorus Systemes
(___, / (_(_(__         	6 avenue Gustave Eiffel
				F-78182, St-Quentin-en-Yvelines-Cedex

Tel: +33 (1) 30 64 82 00	Fax: +33 (1) 30 57 00 66
E-mail: ev@chorus.fr		or ev%chorus.fr@mcsun.EU.net


*/


 

wmm@world.std.com (William M Miller) (03/25/91)

ev@chorus.fr (Eric Valette) writes:
>  *      I would like to have opinions about the best way to check constructor
>  *      parameters validity and report error to caller: I think that something
>  *      is missing in the way you can report error to user using Cfront 2.0

This is true and is one of the main motivations behind the addition of
exceptions to the language.  In the meantime, about the best that can be
done is to add a member function that can be interrogated after allocation
to ensure that the constructor succeeded; something like

                if (!(p = new some_class) || p->ctor_failed()) {
                   delete p;    // allowed even if p == 0
                   // handle cleanup
                   }

-- William M. Miller, Glockenspiel, Ltd.
   wmm@world.std.com

fkuhl@maestro.mitre.org (F. S. Kuhl) (03/26/91)

In article <1991Mar25.154302.4357@world.std.com>, wmm@world.std.com (William M Miller) writes:
|> 
|> This is true and is one of the main motivations behind the addition of
|> exceptions to the language.  In the meantime, about the best that can be
|> done is to add a member function that can be interrogated after allocation
|> to ensure that the constructor succeeded; something like
|> 
|>                 if (!(p = new some_class) || p->ctor_failed()) {
|>                    delete p;    // allowed even if p == 0
|>                    // handle cleanup
|>                    }

Is it true that a constructor returns NULL if it fails?  A quick
look thru ARM failed to settle this point.
-- 
Frederick Kuhl			fkuhl@mitre.org
Civil Systems Division
The MITRE Corporation

sarima@tdatirv.UUCP (Stanley Friesen) (04/08/91)

In article an article fkuhl@maestro.mitre.org (F. S. Kuhl) writes:
>Is it true that a constructor returns NULL if it fails?  A quick
>look thru ARM failed to settle this point.

No, in fact a constructor never returns anything at all.  It cannot,
since it may be called in contexts other than operator new(). For instance,
given the class type 'T' the following calls a default construcor:

T t_obj;

There is no meaningful way to return anything in this context.

As far as I am concerned this is why the error handling stuff in ARM is so
vital, since it is the *only* structured solution to this problem.
-- 
---------------
uunet!tdatirv!sarima				(Stanley Friesen)