How to return error code from constructor?

11,224

Solution 1

According to isocpp.org, the proper way to handle the failure in a constructor in C++ is to :

Throw an exception.

It's not possible to use error code since constructors don't have return types. But :

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.

But you should really use exceptions to signal failure in constructors if you can, as said :

In practice the “zombie” thing gets pretty ugly. Certainly you should prefer exceptions over zombie objects, but if you do not have the option of using exceptions, zombie objects might be the “least bad” alternative.

Solution 2

By adding a layer of abstraction over your constructor, you can achieve your goal of checking to see if a constructor has failed and return an error code. By using a Initialize-Shutdown pattern, you can ensure that if an error occurs somewhere in your constructor, you'll still have access to your object to cleanup anything that you allocated. Here's an example:

// This model we can potentially throw an exception from the constructor
class Keyboard {
private:
    Device* mDevice;
public:
    Keyboard() { 
        mDevice = ConnectToDevice();
        mDevice->Init(); // Say this can throw exception } // If exception thrown, the destructor is not called and memory is leaked
                                                          // The object no longer exists, no way to clean up memory

    ~Keyboard() { DisconnectFromDevice(mDevice); } // DisconnectFromDevice() cleans up some dynamically allocated memory
};

// In this model we use a Initialize-Shutdown pattern
class Keyboard {
private:
    Device* mDevice;
    bool IsInitialized = false;
public:
    Keyboard() {} 
    ~Keyboard() { DisconnectFromDevice(mDevice); } // DisconnectFromDevice() cleans up some dynamically allocated memory
    void Initialize() {
        mDevice = ConnectToDevice();

        if (this.mDevice == nullptr)
            status = -1;

        mDevice->Init(); // Caller still needs to catch exception if it throws
                        // If exception is thrown here, the caller is responsible for cleaning up
                        // However, the object is still alive so caller can manually call or other cleaning method
        
        IsInitialized = true;
        
        return;
    }
    void Shutdown() {
        if (IsInitialized)
            DisconnectFromDevice(mDevice);

        return;
    }
};
Share:
11,224
vanta mula
Author by

vanta mula

Updated on June 13, 2022

Comments

  • vanta mula
    vanta mula almost 2 years

    I am trying to return error code from constructor, since constructor does not return an error code, I tried to put an exception on the constructor. Then in the catch block I return my appropriate error code. Is this a proper way of returning error code from constructor ?

    #include <exception>
    #include <iostream>
    
    class A {
     public:
      A() { throw std::runtime_error("failed to construct"); }
    };
    
    int main() {
      try {
        A a;
      } catch (const std::exception& e) {
        std::cout << "returining error 1 \n";
        return 1;
      }
    
      return 0;
    }