Hi,

As we know constructor doesn't have any return value so it is not good idea to perform exceptional handling inside constructor.SO i would like to know if i am opening a file inside constructor and due to some reason (file not exist) failure happened inside constructor then how to tackle this issue. so below are some questionin my mind

(1) should we perform exceptional handling inside constructor.
(2) if failure (file opening falure) happens inside constructor, does it going to affect the object state. I mean to say object is going to be currupted. if yes then what are the best way to address this issue. I would be happy if you share your thoughts with good example.

Recommended Answers

All 17 Replies

  1. C++ Primer 5th Ed. Chapter 18. Section 1.3 pg. 953-955. There is an exercise there to practice this new technique.
  2. No, technically the object is not yet constructed. Do the exercise 18.7 C++ Primer 5th Ed. Then stress test your object to your hearts content.
  1. Don't throw exceptions from a constructor.
  2. See #1.

If you do have an exeptional condition inside a constructor, then you need to set a member variable indicating that the construction failed. Remember, your object may be the base of another that will naturally call your constructor. If you throw an exception, the derived class object will never see it, though the constructing code should be able to catch the exception, but it can also check the base class exception variable to determine that the object construction failed at some level.

  1. Test, test, test!
  2. See above.

Make sure your unit tests force such conditions to see how well they are handled and that you can handle them sanely. Is your code running a nuclear power plant? A plane in flight? Don't let "good enough" be your philosophy!

Like Moschops link says, the options are basically between using a zombie state or throwing from the constructor. The latter is the ideal solution, for an ideal world in which you can adopt exceptions wholesale for everything. Unfortunately, the real world is not very ideal, and therefore, the zombie state solution is the most common one.

#include <iostream>
using namespace std;


class A
{ int *memory;
public:

  A(){
    try{

   memory= new int [100000000000000];
    }
catch(bad_alloc &memmoryAllocationException ){
      cout << "Memory allocation exception occurred\n";
      cout<<memmoryAllocationException.what();
    }


  }
};

int main (int argc, const char * argv[])
{

  A a;
  return 0;
}

could you let me know what is the wrong with above code snippet. Is this right way to tackle the exception inside the constructor. zombie state can be opt if exceptional handling can't be done.
" If you don’t have the option of using exceptions, the “least bad” work-around is to put the object into a “zombie” state by setting an internal status bit so the object acts sort of like it’s dead even though it is technically still alive".

There is a school of thought that says that you should not really design your class such that you're having to actually do things that could fail in the constructor. You should instead "inject" the things that the class needs directly into the constructor, which should simply be a thing that assigns the dependencies to the right places in the class. So, for something that requires a files to read from, you would pass some pointer or reference to the stream you want to read from into the construtor directly. Along with this comes some additional infrastructure in the form of "factories" that actually do the work of building all the dependencies for the class. So, a simple example would look something like this:

[Compiles with Clang 3.7.0 (Trunk)]

#include <iostream>
#include <fstream>
#include <memory>
#include <string>

/// Our class that we want to make
class A
{
    // Member that we want to initialise
    std::ifstream _is;

public :   

    /// Factory function that takes care of the business of actually building all the dependencies of the class
    static std::unique_ptr< A > Create( const std::string& file_name )
    {
        std::ifstream is( file_name.c_str() );
        if ( ! is.is_open() )
            return nullptr;   // Return null if we fail - no exceptions here!

        return std::unique_ptr< A >( new A( std::move( is ) ) );
    }

    /// Constructor just does very simple things that can't really go wrong
    A( std::ifstream&& is ) : _is( std::move( is ) ) {}
};

int main()
{
    /// Make a new instance of an A
    auto a = A::Create( "/some/file/path.txt" );
    if ( ! a )
        std::cout << "Failed to make an A" << std::endl;
    else
        std::cout << "Yay! A created" << std::endl;

    return 0;
}

This is a useful pattern in the case that you can't let exceptions leak out. It's also useful if you want to unit test your classes.

commented: good one. +2

Thanks for wonderfull demonstration of this problem. one more thing which i would like to know , what are the real drawbacks of using exceptional handling inside constructor. The link which shared by moschops ,there it is clearly mentioned that we should throw the exception so now i am little bit consfusedI.It will be real helpful if throw some light on this. in some article it was mentioned that constructor can do N number of allocation, and if one gets fail then why construction should be suffered as the job of constructor to bring the object in existance.

I think it makes things more complicated.

Say something throws part way through some complicated constructor, now the destructor will be called and you will be trying to clean up some half-initialised thing in some unknown state. Not impossible, but it's going to make the code more complicated than it needs to be for sure.

Now also imagine that your class (A) with a throwing constructor is a member of another class (B). Now B might call the (throwing) constructor via itsinitialiser list. If an exception is thrown here, I don't actually know what happens. I don't know if B's destructor will be called, since there isn't technically a B to destruct at this point. The compiler might keep track of all the things that it's made so far and call their destructors separately, I don't know. If you look it up and find out, definitely post a link or explanation :0)

The link which shared by moschops ,there it is clearly mentioned that we should throw the exception so now i am little bit consfusedI.

That link adopts the "modern" view of C++ coding practices that basically embraces the widespread use of exceptions. Under that point of view, throwing an exception from the constructor is definitely the preferred way. The people who advise against throwing exceptions in a constructor (e.g., rubberman, see above) are really advocating against the adoption of exceptions (or at least, a very conservative use of exceptions). Under that point of view (which, as I said, is often the more "realistic" policy), it's preferrable to leave the object in a zombie state instead of throwing.

So, it all boils down to the perpetual debate between using exceptions or using more traditional error-checking mechanism (zombie states, "bad" flags, error codes, etc.). There is no universal answer to this debate. It depends too much on the context, as in, where, when, and who, which means where is the code running (e.g., embedded vs. desktop), when was most of the existing code written (e.g., brand new project vs. large legacy code-base), and who is writing the code (e.g., what are your programming team most used to and thus, less likely to do wrong).

in some article it was mentioned that constructor can do N number of allocation, and if one gets fail then why construction should be suffered as the job of constructor to bring the object in existance.

I'm not sure I understand exactly what you are saying there, but I'm pretty sure what you are referring to is a classic problem about having multiple resource (e.g., memory allocations) within a single class. The problem with that is that there is no nice / clean way to deal with all the multiple failure scenarios (any one of the operations could fail). It just gets messy when you have to worry about cleaning up (or reverting or releasing) the parts that worked but not the parts that failed.

The general solution to this, which is an undisputed universal guideline in C++, is to have 1 class == 1 resource. In practice, this usually means that classes should be designed such that there is really only one operation that could fail in their constructor. This is a part of the RAII principle (Resource Acquisition Is Initialization), which states that if you have a resource to handle (a resource is basically anything that requires a "acquire" and a "release" step, such as a memory allocation / deallocation, file opening / closing, internet socket connecting / closing, etc..), then you should have one class to handle that one resource, and that class' constructor should acquire the resource (or fail, with an exception or zombie state) and its destructor should release the resource. This principle is by far the most important coding principle in C++.

Now B might call the (throwing) constructor via itsinitialiser list. If an exception is thrown here, I don't actually know what happens.

This is actually pretty simple once you understand two fundamental rules: (1) everything that has been constructed will be destructed; and, (2) an object is considered constructed when it leaves the body of its constructor (closing curly brace). So, when the A member of B throws on construction, it has not been constructed, so it won't be destructed, and the same for the parent B object. Any member of B that was constructed before the A member constructor was called will be destructed. So, as you see, it's pretty simple, it's just a recursive application of the aforementioned 2 principles. And this is a very solid air-tight guarantee given by the C++ standard. And a third principle applies too, which is that everything is destructed in the exact reverse order of their construction, which is also a very strict standard guarantee.

Dear mike , Thanks for again good explanation .

when the A member of B throws on construction, it has not been constructed, so it won't be destructed, and the same for the parent B object.

so you want to say that this is the drawback of this approach(throwing exception from constructor)as my code moderator also suggested the same and asked me not to throw exception from constructor . He suggested by refering RAII principle that destructor should be run in any circumstances.Below appraoch was suggested by him for handling the file operations.based on your 1 class == 1 resource and my moderator's suggestion I have designed class according tp below code snippet by delegeting File operation responsibility to MYFile class .
Please let me know your thought on this.

class MyFile {
public:
    MyFile() {}

    ~MyFile() {
        if(_file.isOpen()){
            _file.close();
        }
    }

    void open(const char* filename) {
        _file.open(filename);
    }

    bool isOpen() const {
        return _file.isOpen();
    }

    void close() {
        if(_file.isOpen()){
            _file.close();
        }
    }

    std::string readLine() {
        return _file.readLine();
    }

private:
    File _file;
};

MyFile f;
f.open("boo.txt");
//SAFE - The MyFile destructor is guaranteed to run
loadFromFile(f);

Hi mike and revenous,

I have observed that after throwing exception from class A during construction
still i am able to call the destructor of class B and ClassA. Please let me know your thought on this.

#include <iostream>
using namespace std;
class A
{
int *memory;
public:
A()
{
cout<<"calling constructor class A\n";
try 
{

memory= new int [100000000000000];
}
catch (bad_alloc &memmoryAllocationException )
{
cout << "Memory allocation exception occurred\n";
cout<<memmoryAllocationException.what();

}

}
void show()
{
cout<<"show A\n";
}
~A()
{
cout<<"calling destructor class A\n";
}

};


class B
{
public:

B()
{
cout<<"calling B's constructor\n";

}

~B()
{
cout<<"calling B's destructor\n";

}
void show() { a.show();}
private:

A a;

};

int main()
{

B obj;
obj.show();

return 1;
}

Output:

calling constructor class A
Memory allocation exception occurred
std::bad_alloc
calling B's constructor
show A
calling B's destructor
**calling destructor class A
**

Looks to me like you aren't throwing an exception from the constructor of A.

In this code, the constructor of class A clearly finishes and returns; no exception is thrown from the constructor of class A. If you want the constructor to throw an exception, don't deal with that exception inside the constructor.

Then how same will be achieved.i also tried to simulate this scenario from below code snippet and found the same result.

A()
{
cout<<"calling constructor class A\n";
try
{

throw 10;
}
catch (int )
{
cout << "exception: integer is not expected";


}

if we don't deal with that exception inside the constructor then programme will abort and below output will come.
**Non memory related check **
calling constructor class A
terminate called after throwing an instance of 'int'
Aborted

memory related :
calling constructor class A
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc

below is good link which explains that how to tackle this kind of issue, but still i am not able to implement the how we can write a function-try-block for B's constructor. It seems to be B should have been privately derived instead of composition.

Link:

http://www.gotw.ca/gotw/066.htm

if we don't deal with that exception inside the constructor then programme will abort and below output will come.

No. If you never deal with the exception AT ALL the programme will abort. So catch it. Throw the exception from the constructor, and catch it.

#include <iostream>
using namespace std;
class A
{
  int *memory;
  public:
  A()
  {
    cout<<"calling constructor class A\n";
    memory= new int [100000000000000];
  }
  void show()
  {
  cout<<"show A\n";
  }
  ~A()
  {
    cout<<"calling destructor class A\n";
  }
};

class B
{
  public:
  B()
  {
    cout<<"calling B's constructor\n";
  }
  ~B()
  {
    cout<<"calling B's destructor\n";
  }
  void show() { a.show();}
  private:
  A a;
};

int main()
{
  try 
  {
    B obj;
    obj.show();
  }
  catch (bad_alloc &memmoryAllocationException )
  {
    cout << "Memory allocation exception occurred\n";
    cout<<memmoryAllocationException.what();
  }

  return 1;
}

Thanks moschops.Do you have any idea , how to achieve same by implementing function-try-block
this approach will also help to catch the exception till last inherited class.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.