Online Book Reader

Home Category

Professional C__ - Marc Gregoire [173]

By Root 1388 0
either rethrow the current exception or throw a new exception. The preceding catch statement does not throw anything, so the C++ run time will automatically rethrow the current exception. Following is a simple function that uses the preceding class:

int main()

{

try {

MyClass m;

} catch (const std::exception& e) {

cout << "main() caught: '" << e.what() << "'" << endl;

}

return 0;

}

Code snippet from FunctionTryBlock\FunctionTryBlocks.cpp

The output of the preceding example is as follows:

function-try-block caught: 'Exception by SubObject ctor'

main() caught: 'Exception by SubObject ctor'

Function-try-blocks are not limited to constructors. They can be used with ordinary functions as well. However, for normal functions, there is no useful reason to use function-try-blocks because they can just as easily be converted to a simple try/catch block inside the function body. One notable difference when using a function-try-block on a normal function compared to a constructor is that rethrowing the current exception or throwing a new exception in the catch statements is not required and the C++ run time will not automatically rethrow the exception.

Errors in Destructors

You should handle all error conditions that arise in destructors in the destructors themselves. You should not let any exceptions be thrown from destructors, for three reasons:

1. Destructors can run while there is another pending exception, in the process of stack unwinding. If you throw an exception from the destructor in the middle of stack unwinding, the program will terminate. For the brave and curious, C++ does provide the ability to determine, in a destructor, whether you are executing as a result of a normal function exit or delete call, or because of stack unwinding. The function uncaught_exception(), declared in the header file, returns true if there is an uncaught exception and you are in the middle of stack unwinding. Otherwise, it returns false. However, this approach is messy and should be avoided.

2. What action would clients take? Clients don’t call destructors explicitly: they call delete, which calls the destructor. If you throw an exception from the destructor, what is a client supposed to do? It can’t call delete on the object again, and it shouldn’t call the destructor explicitly. There is no reasonable action the client can take, so there is no reason to burden that code with exception handling.

3. The destructor is your one chance to free memory and resources used in the object. If you waste your chance by exiting the function early due to an exception, you will never be able to go back and free the memory or resources.

Therefore, be careful to catch in a destructor any exceptions that can be thrown by calls you make from the destructor. Normally, destructors call only delete and delete[], which cannot throw exceptions, so there should be no problem.

PUTTING IT ALL TOGETHER


Now that you’ve learned about error handling and exceptions, let’s see it all coming together in a bigger example, a GameBoard class. This GameBoard class will come back in Chapter 19. First, here is the definition of the class without any exceptions.

class GameBoard

{

public:

// general-purpose GameBoard allows user to specify its dimensions

GameBoard(int inWidth = kDefaultWidth,

int inHeight = kDefaultHeight);

GameBoard(const GameBoard& src); // Copy constructor

virtual ~GameBoard();

GameBoard& operator=(const GameBoard& rhs); // Assignment operator

void setPieceAt(int x, int y, const GamePiece& inPiece);

GamePiece& getPieceAt(int x, int y);

const GamePiece& getPieceAt(int x, int y) const;

int getHeight() const { return mHeight; }

int getWidth() const { return mWidth; }

static const int kDefaultWidth = 100;

static const int kDefaultHeight = 100;

protected:

void copyFrom(const GameBoard& src);

// Objects dynamically allocate space for the game pieces.

GamePiece** mCells;

int mWidth, mHeight;

};

Code snippet from GameBoard\NoExceptions\GameBoard.h

And here is the implementation without any exceptions:


Return Main Page Previous Page Next Page

®Online Book Reader