Archived

This topic is now archived and is closed to further replies.

Spartacus

How to report when an constructor fails???

Recommended Posts

Hey! How can I report to the calling function when the constructor of an object fails? Lets say I have a constructor like this: CObject::CObject(const CHAR srcFile[MAX_PATH]); and this constructor takes the path to a bmp file and loads the file. If the file does not exist, for instance, how can I notify the function constructing the object of this behaviour? Do I have to use exceptions or what?¿? Thanks! Spartacus

Real programmers don''t document, if it was hard to write it should be hard to understand

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Yes, you have to use an exception.

Another horrible way to do it is for the constructor to set a flag indicating it was constructed correctly and then check the flag each time an object is created.

Share this post


Link to post
Share on other sites
I suppose exceptions could do it, or perhaps have a flag that gets set in the class that''ll tell the caller whether the object''s properly initialized or not. Still, I think the best way would to simply move any code that could fail right out of the constructor to somewhere else where it''ll be easier to test for failure.

Share this post


Link to post
Share on other sites
There are three ways I can think of to do this:

1. as Melraidin said, move the initilisation out of the Constructor.

2. Melraidin''s other suggestion, set a flag and add an isValid() method.

3. Create a static method to construct the object, something like:

int clone(CObject* object, const CHAR srcFile[MAX_PATH]);

This can return an error code if anything goes wrong.

Exceptions would probably also work.

Pick whatever you like best!

Enigma

Share this post


Link to post
Share on other sites
Throw an exception. That will ensure that your partially constructed object gets cleaned up correctly. i.e. the destructors for the members that have actually been constructed will be called.

The proper place for initialisation code _is_ the constructor. "Ressource acquisition is initialisation" does wonders.

Documents [ GDNet | MSDN | STL | OpenGL | Formats | RTFM | Asking Smart Questions ]
C++ Stuff [ MinGW | Loki | SDL | Boost. | STLport | FLTK | ACCU Recommended Books ]

Share this post


Link to post
Share on other sites
quote:
Original post by kill
Correct me if I''m wrong, but throwing exceptions from a constructor might (and in some cases definetly will) result in a memory leak.

If throwing an exception in a constructor will result in a memory leak, your design is flaw.

Share this post


Link to post
Share on other sites
kill:
C++ spec says that if a constructor fails (throws an exception), the memory for the object being constructed is released. You wouldn't, for instance, write this code:

    
Widget *pw;
try
{
pw = new Widget;
}
catch (...)
{
delete pw; // no need for this! memory already released!

}

In fact, if you tried running this code as-is, you might get a memory access violation because if Widget's ctor fails, the assignment to pw never happens.

[edited by - Stoffel on August 13, 2002 6:24:48 PM]

Share this post


Link to post
Share on other sites
Google is your friend.
Constructor Failures (or, The Objects That Never Were)

    
class foo
{
public:
foo()
try
: myBar( /*...*/ )
{
// The other constructor code goes here.

}
catch ( ... )
{
// The exception handling code goes here.

}
private:
bar myBar;
};

EDIT1: Fixed google link...

[edited by - dalleboy on August 13, 2002 7:55:55 PM]

Share this post


Link to post
Share on other sites
I''m pretty sure there were other people wondering about it too
Thanks!


"It is precisely because it is fashionable for Americans to know no science, even though they may be well educated otherwise, that they so easily fall prey to nonsense. They thus become part of the armies of the night, the purveyors of nitwittery, the retailers of intellectual junk food, the feeders on mental cardboard, for their ignorance keeps them from distinguishing nectar from sewage."
Isaac Asimov

Share this post


Link to post
Share on other sites
quote:
Original post by Arild Fines
I''m pretty sure there were other people wondering about it too

Indeed

Ugly syntax (we''re talking about exceptions, after all), but interesting. Thanks for the link.

Cédric

Share this post


Link to post
Share on other sites
Exceptions aren''t that ugly, the only problem I have is they make your code a bit longer on the screen to look through. Though a try-block around 10 things is nicer than having to do an if(whatever failed){sort it out} for each line, especially since those ''sort it out''s will often be largely the same.



Read about my game, project #1
NEW (13th August): A new screenshot is up, plus diaries for week #3


John 3:16

Share this post


Link to post
Share on other sites
Exceptions solve these problems nicely, but I still hate the syntax; try-catch blocks don''t follow the same pattern as if-else, do, while, for, switch, etc. The logic is ''when an exception is thrown, get out of the try block, look for a matching catch, and run there''. Do you know of any other structure in C++ that does anything similar? I guess that''s why they''re called ''exceptions''.

Anyway, this is pointless (not to mention OT), because I have no idea how it could have been done better.

Cédric

Share this post


Link to post
Share on other sites
quote:
Original post by Magmai Kai Holmlor
It can, you have to code everything to be exception safe. Either use RAII religiously or use constructor-try blocks (which MSVC doesn''t support).


RAII is the way to go. I would say using constructor-try blocks or anything that has lots of try/catch or __try/__finally (VC++ Structured Exception Handling) should use return codes instead.

If you need try/catch to handle exceptions, chances are you need rollback capability when an exception occurs. Look for "Scopeguard" article in www.cuj.com

The only valid (logical) uses for constructor-try blocks I have seen is for trapping exceptions thrown during ctor of static objects. These objects are created before main, and if their ctor throws, there is no way to catch them. So, you can trap the exception by initializing the stat object through a exception_trapper with constructor-try blocks, and when main is entered, check whether there is any thrown exceptions. There is a old thread in comp.lang.c++.moderated that discusses this. Search for "constructor try", I believe.

Share this post


Link to post
Share on other sites
quote:
Original post by tangentz
Item #17 and #18 of More Exceptional C++ (by Herb Sutter) talk
about contructor fucntion try blocks and how they have little
or no practical use. You can also find the original articles
at Guru of the Week.


More or less. He says that the only (repeat only) possible use for a constructor function try block is to translate an exception thrown from a base or member subobject .

So, constructor try blocks aren't the right way to prevent memory leaks, apparently.

Cédric


[edited by - cedricl on August 14, 2002 9:08:39 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by JackNathan
Using a nearly empty constructor and an Init(...) member function to do the real work is an option.



That may be real ugly for some.

Constructor try blocks are not meant to meant to make the code exception safe. You still need to practice RAII (religiously I may add)

As for how constructor try blocks can be useful, I found the article
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=user-0409991408120001%40aus-as3-128.io.com&rnum=4

Share this post


Link to post
Share on other sites
Hey THANKS for the help everyone, your help is appreciated!!! Actually I didn''t expect THAT many replies. Thanks to everyone who took their time and replyed to my question. I think I was not the only one learning something here

Spartacus



Real programmers don''t document, if it was hard to write it should be hard to understand


Share this post


Link to post
Share on other sites