example:Vector
template <class T> class Vector{
private:T* m_elements;int m_size;
public:Vector (int size = 0):m_size(size)...~Void(){delete [] m_elements;}void length(int);int length(){return m_size;}T& operator[](int);
};
problem
template <class T>
T& Vector<T>::operator[](int indx){}
-
what should the [] operator do if the index is not valid? index 越界怎么办?
1.)return random memory object 不可以
return m_elements[indx];
2.)return a special error value 返回一个特殊错误值 不是好办法
if (indx < 0 || indx >= m_size){T* error_marker = new T("some magic value");return *error_marker; } return m_elements[indx];
*but this throws the baby out with the bath!
x = v[2] + v[4]; //not safe code
3.)just die!
if (indx < 0 || indx >= m_size){exit(22); } return m_elements[indx];
4.)die gracefully (with autopsy!)
assert(indx >= 0 && indx < m_size); // 不合适 retrun m_elements[indx];
when to use exceptions 好的解决办法
-
many times ,you don’t know what should be done
-
if you do anything you’ll be wrong
-
solution:turf the problem
make your caller(or its caller…) responsible
how to raise an exception
template<class T>T& Vector<T>::operator[](int indx){if(indx < 0 || indx >= m_size){//throw is a keyword//exception is raised at this pointthrow --someting--}return m_elements[indx];}
what do you throw?
//what do you have? Data!
//define a class to represent the error
class VectorIndexError{
public:VectorIndexError(int v):m_badValue{}~VectorIndexError(){}void diagnostic(){cerr << "index" << m_badValue <<"out of range";}
private:int m_badValue;
};
how to raise an exception
template<class T>
T& Vector<T>::operator[](int indx){if(indx < 0 || indx >= m_size){//VectorIndexError//throw e;throw VectorIndeError(indx); // VectorIndeError对象在堆栈里面}return m_elements[indx];
}
what about your caller?
-
case 1 Doesn’t care
-
code never even suspects a problem
int func(){Vector<int> v(12);v[3] = 5;int i = v[42];//out of range//control never gets here!return i*5; }
-
-
case2 cares deeply
void outer(){try{func(); func2(); // func2 不执行}catch(VectorIndexError& e){e.diagnostic();//this excpetion does not propagete}cout << "control is here after exception" }
-
case3 mildly interested
void outer2(){String err("exception caught");try{func();}catch(VextorIndexError){cout << err;throw; //propagate the exception} }
-
case4 does’t care about the particulars
void outer3(){try {outer2();}catch(...){ // 捕捉所有异常//...catches **all** exceptions!cout << "the exception stops here"} }
what happened?
review
-
throw statement raise the exception
- control propagates back to first handler for that exception
- propagation follows the call chain
- objects on stack are properly destroyed
-
“throw exp”
- throws values for matching
-
“throw”
- reraises the exception being handled
- valid only within a handler