BLM> I'd like the opinion of the folks in this echo concerning the
BLM> following statement from the book "Black Belt C++..."
I though it was a good book. Eckel is a good writer and a good
editor! His book, "Thinging in C++" is also good.
BLM> C programmers are faced with two temptations in writing
BLM> constructors:
BLM>
BLM> o The temptation to ascribe too much responsibility to
BLM> the constructor. The constructor's responsibility is
BLM> to "make an object out of a bunch of raw bits." Just
BLM> that, and no more. A constructor that has sweeping
BLM> side effects is normally poor programming practice
BLM> because constructors can be called by the compiler
BLM> when you least expect it. This can introduce exposure
BLM> to buggy behavior or inefficiency.
The thing to consider most is, who is the customer for the class.
Are you writing classes which you expect others to use and
inherit from? Or is this an "internal use" type of class where
you have complete control. Eckel's advice (if it were his,
"Black Belt" was a collection of essays from various authors)
applies more to those writing classes for others.
BLM> o The temptation to write a constructor to create an
BLM> object of a user defined type from just about any
BLM> other type imaginable. Conversion by construction is
BLM> not bad, but it is important to define what sort of
BLM> conversions make sense up front.
BLM> ''
This should become less a problem when more compilers support
'explicit' and more programmers take advantage of it.
BLM> How would you define "ascribing to much responsibility to the
BLM> constructor?" Is this to much...
BLM> manifest::manifest(){
BLM> filename = new char[FILENAME_MAX];
BLM> while (!select(filename, FILENAME_MAX - 1));
BLM> mstreamp = new ifstream(filename);
BLM> }
The "problem" with the above constructor is error detection/recovery.
If you want to throw exceptions and those who use your code are willing
to put up with code that throws exceptions, then that's what you
ought to do.
But there's also a lot to be said for creating constructors that will
not, under any circumstances, throw an exception. Think about the
following code.
void foo() {
MyClass x;
//lot's of code
DoSomething (x);
}
You cannot handle an exception on the constructor of x with a try
catch block just around the definition.
void foo() {
try {
MyMclass x]
}
catch (SomeException e) {...}
...
DoSomething(x);
}
Because now x is no longer in scope for the call to DoSomething(). Of
course you can get around that by enclosing the entire body of the
routine in a try/catch block. But then your catch block may not be
satisfactory for detecting an exception thrown in the constructor and
the same exception thown in the code block. (You caould also use
a pointer and assign to value of the pointer to the constructed
object after the catch block (yuck!),
Further, consider the case of a global object. How can you catch
an exception thown from its constructor? Well, you can't. So there
are positive advantages to writing constructors that cannot ever fail,
if at all possible.
---
þ Blue Wave/QWK v2.12 þ
---------------
* Origin: St. Louis Users Group (1:100/4)
|