function try block is a block which the entire body of the function body is encosed in a try cluase block;
for better illustration, let see some examples which can better serve for our dicussion purpose later on the exception handling issues.
Let's first introduce the the test code that we are going to use, it is a home made iStack class;
the header file of the stackExcp.h is as follow.
/*** * @summary * stackExcep.h is the header file that define the class that is called iStack, which we will use as the data object to manipulate and demonstate the use * of exception in C++ */ #include <vector> using std::vector; class iStack { public : iStack(int capacity ) : _stack(capacity) , _top(0) { } void pop(int & top_value) ; void push (int value); bool full(); bool empty(); void display(); int size(); private: int _top; vector <int> _stack; }; /** * @Summary * to demonstrate the use of Exception, we are going to define two classes, one is the * popOnEmpty() * the other is * pushOnFull */ class popOnEmpty { /* .... */ }; class pushOnFull { /* ... */ };
part of the stackExcp.'s implementation is as follow.
#include "stackExcp.h" #include <iostream> using std::cout; using std::endl; void iStack::pop(int &top_value) { if (empty()) { throw popOnEmpty(); } top_value = _stack[--_top]; cout << "istack::pop(): " << top_value << endl; } void iStack::push(int value) { cout << "istack::push( " << value << " ) \n"; if (full()) { throw pushOnFull(); } _stack[_top++] = value; } bool iStack::empty() { return _top <= 0; } bool iStack::full() { return _top > _stack.capacity(); // a common pitfall is tha the use _stack.size(); } void iStack::display() { cout << "display: ( "; for (int i = 0; i < _top; ++i) { // a common case of error is that if you write as follow // the code will be like this: // cout << _stack[i} << ( i == _top - 1) ? ")" : ""; // it will output some wierd output , guess the compiler try to output the value of the condition test part of the the ternary expression // that is because of the order of the execution , // where the ?: has a lower precedence than the << operator // so it will first output the evalution value of the condition expression and then if depends on the return resutlt, which is a cout << _stack[i] << " " << ((i == _top - 1) ? " )" : "") ; if (i != 0 && i % 8 == 0 || i == _top - 1 ) cout << endl; } }
normally we will write c++ code as follow :
void intermixedTryClause() { iStack stack(32); for (int ix = 0;ix < 51; ++ix) { try { if (ix % 3 == 0) { stack.push(ix); } } catch (pushOnFull) { //cout << "caught error on pushOnFull" << endl; } if (ix % 4 == 0) { stack.display(); } try { if (ix % 10 == 0) { int dummy; stack.pop(dummy); stack.display(); } } catch (popOnEmpty) { //cout << "caught error on popOnEmpty" << endl; } } }
as you can see we intermix the body of the function with that of exception handling, which does not follow the separation rule that implementation code should be separated from its error handling code.
there is a small technique that you can try to make the function body more fun, which as many reader has figured out, it is the function try block, let's see how it works out.
/** * Below test the function try body techniques where you can put the try clause with the catch clauses right after the function body without * the function opening body '{' or the function closing body '}' */ void functionTryBody() try { iStack stack(32); for (int i = 0; i < 51; ++i ) { int val; if (i % 3 == 0) stack.push(i); if (i % 4 == 0) stack.display(); if (i % 10 == 0) { stack.pop(val); stack.display(); } } } catch (popOnEmpty) { /* */ } catch (pushOnFull) { /* */ }
so directly follow the function declaration is the try keyword , then is the try body followed by several catch handlers and body;