Thread: Class Constructor error handling

  1. #1
    uh oh
    Join Date
    Jan 2005
    Location
    Ontario, CA
    Posts
    66

    Class Constructor error handling

    Is there any good resources to show the possible methods one could use in order to better handle errors that may occur during the class constructor call?

    I know of the throw() and catch() method but, just wondering if there are more efficient or just plain better methods to use in order to deal with such situations.

    Thanks

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by cyreon View Post
    Is there any good resources to show the possible methods one could use in order to better handle errors that may occur during the class constructor call?

    I know of the throw() and catch() method but, just wondering if there are more efficient or just plain better methods to use in order to deal with such situations.

    Thanks
    There are two standard methods.

    1. If construction fails, throw an exception. This is normally the best method.

    2. If for some reason you cannot throw an exception, split construction into two phases: construct, then initialize.

    Code:
    SomeObject a;
    if(!a.Initialize(...))
    {
        // something went wrong
    }
    You'd do this if, for instance, you were targetting an environment that did not support exceptions. Or, if the main body of code is not exception-safe, you do not want to introduce exceptions that may cause logical errors or resource leaks.

    The choice to not use exceptions is a serious choice. Once you have decided that your design will not use exceptions, this decision is very hard to reverse, because code will have been written without taking exception-safety into account. Make sure you are making the right decision at the outset, because it is extremely difficult to change it.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  3. #3
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Constructor calls can not "fail" in any other ways than by throwing an exception [and in some cases/systems, constructor calls are not allowed to fail at all - if a class has some further work that needs doing that may fail, that has to be done in a separate method, after the class has been constructed - this would mean for example not calling new].

    Since constructors in themselves can not return an error, the constructor can not inform the calling code about it's "succes" or "failure". And it is also a case of clean-up. If, for example, a constructor "returns" before the construction is finished, how does the object get cleaned up?
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  4. #4
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by matsp View Post
    Constructor calls can not "fail" in any other ways than by throwing an exception [and in some cases/systems, constructor calls are not allowed to fail at all - if a class has some further work that needs doing that may fail, that has to be done in a separate method, after the class has been constructed - this would mean for example not calling new].

    Since constructors in themselves can not return an error, the constructor can not inform the calling code about it's "succes" or "failure". And it is also a case of clean-up. If, for example, a constructor "returns" before the construction is finished, how does the object get cleaned up?
    --
    Mats
    Sure you can return a success or failure in a constructor, you just have to do it with a parameter. Ex.
    Code:
    class Something
    {
       Something( bool&  constructedSuccessfully )
       {
          constructedSuccessfully = false;
          ...
          // If nothing fails, set it to true.
          constructedSuccessfully = true;
       }
    };
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  5. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by cpjust View Post
    Sure you can return a success or failure in a constructor, you just have to do it with a parameter. Ex.
    Code:
    class Something
    {
       Something( bool&  constructedSuccessfully )
       {
          constructedSuccessfully = false;
          ...
          // If nothing fails, set it to true.
          constructedSuccessfully = true;
       }
    };
    That's the cousin of the Initialize() method I showed above. Both have serious drawbacks. The fundamental problem is how to deal with the members that DID construct successfully. If these members are held by value, you have two options to destruct them, both of which suck:

    1. Call Something::~Something() on yourself. This is wrong, because the object was never fully constructed in the first place.

    2. Explicitly invoke the destructors of the completely constructed members. Gag me. They'll be double-destructed when the Something object goes out of scope, which it will do very soon, since it is invalid.

    The workaround is to hold all members dynamically by pointer. Now you're doing really stupid stuff just because you have to avoid throwing inside a constructor. The bottom line is, if you have this restriction, life blows.
    Last edited by brewbuck; 02-17-2009 at 05:15 PM.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  6. #6
    uh oh
    Join Date
    Jan 2005
    Location
    Ontario, CA
    Posts
    66
    This question seems to have opened up a discussion, thanks for all of your input. I'm not sure if perhaps I am doing things wrong, but in the case of construction failure I do end up calling the deconstructor to destroy it, however, my deconstructors are built in a fashion that they verify data entries prior to releasing them and thus only what has already been initialized/created will be removed and those items that failed on creation will not even be touched. Is this something that I shouldn't be doing?

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by cyreon
    my deconstructors are built in a fashion that they verify data entries prior to releasing them and thus only what has already been initialized/created will be removed and those items that failed on creation will not even be touched. Is this something that I shouldn't be doing?
    How can you "verify data entries" such that "those items that failed on creation will not even be touched" unless all your data members are pointers? That is what brewbuck was talking about in the latter part of post #5.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    uh oh
    Join Date
    Jan 2005
    Location
    Ontario, CA
    Posts
    66
    Okay to rephrase, not all members are pointers such that some are simple data members (such as a DWORD, int, etc.) that signifies specific things to the class itself. Though the items to be initialized are infact pointers, I do not understand why this is termed as "doing really stupid stuff". Since a class Deconstructor is called just prior to the main entity being destroyed, is its main purpose not to remove all items that should infact be "cleaned up" (such as dynamic memory chunks)?

    Sorry I've done a lot of C programming but, still grasping all the concepts of C++. Perhaps I have missed something in regards to the Deconstructor... if my opinions are wrong then would anyone have an example of a constructor/deconstructor (from any class) that would show a good example of their true purposes to a class? I am going to do some research on my own to read a bit more about this topic... and pull out the books. lol... now you have me wondering.

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by cpjust View Post
    Sure you can return a success or failure in a constructor, you just have to do it with a parameter. Ex.
    Code:
    class Something
    {
       Something( bool&  constructedSuccessfully )
       {
          constructedSuccessfully = false;
          ...
          // If nothing fails, set it to true.
          constructedSuccessfully = true;
       }
    };
    Yes, I have used this method (or one similar to it) for a work-project which had constructors that returned in case of errors - it was not a good solution, but it was the only solution that didn't involve redesigning an entire class - which would be the right thing to do in the long term.

    And that code looked something like this:
    Code:
         Something s(ok)
         if (ok) 
         {
            ... bunch of code ...
         }
    The reason the constructor woudl fail was that it called a non-throwing new to set a member pointer, and if the result was NULL it returned. The rest of the code, prior to my change, would then try to use the pointer, even when it was NULL - and other members that weren't initialized at all!

    --
    Mats
    Last edited by matsp; 02-18-2009 at 02:24 PM.
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help with FIFO QUEUE
    By jackfraust in forum C++ Programming
    Replies: 23
    Last Post: 04-03-2009, 08:17 AM
  2. Class design problem
    By h3ro in forum C++ Programming
    Replies: 10
    Last Post: 12-19-2008, 09:10 AM
  3. Defining derivated class problem
    By mikahell in forum C++ Programming
    Replies: 9
    Last Post: 08-22-2007, 02:46 PM
  4. matrix class
    By shuo in forum C++ Programming
    Replies: 2
    Last Post: 07-13-2007, 01:03 AM