#include <iostream>
using namespace std;
// 예외이야기- 진짜 예외는 객체를(클래스) 만들어서 계층화 해야 한다.
// 예상치 않은 에러가 난다면 설계가 잘못된 것.(사용자가 지정하지 않은 에러)
// 롤백- 예외 발생시 다시 안전된 상태로 돌려놔야 한다.
class Exception {};
class StackException : public Exception {};
class StackUnderflowException : public StackException {};
// 예외 안전성의 개념
// 1. 기본보장: 예외 처리후 메모리등의 리소스낭비는 없지만 프로그램의 상태를 알
수는 없다.
// 2. 강력보장: 예외를 처리한 후 프로그램의 상태가 예외발생 이전으로 복구된다.
// 3. 완전보장: 예외가없다. int a = 10;
// 예외중립( Exception neutral )
// exceptional c++
http://cafe.naver.com/cppmaster/1516
class Test
{
int buf[100];
public:
Test() { throw 1; }
};
void main()
{
try
{
Test* p = new Test; // 1. 메모리할당
// 2. 생성자호출- 그런데예외가나왔다.
// (1)에서 할당한 메모리는 해지되었을까?? 낭비인가??
// new 자체에서 에러 발생시 낭비를 방지하는 코드가 있다.
}
catch( int )
{
}
}
void foo() // 어떠한 예외라도 나올 수 있다. 예외가 없다는 throw()를 붙여줘야 한다.
{
try
{
char* p = new char;
}
catch( std::bad_alloc e )
{
// 어떻게 처리할까?
// 1. 메모리를 재할당해서 성공할 수 있다면 ok.
// 2. 그렇지 않다면 호출자에게 다시 전달.. - 예외중립
throw;
}
}
// 아래 대입 연산자가 예외안전성을 지원하는가?
class String
{
char* buff;
int sz;
public:
String& operator=( const String& s )
{
if ( &s == this ) return *this;
char* temp = new char[ s.sz+1 ]; // 예외가 발생 할 수도 있다.
strcpy( buff, s.buff );
// 예외가 발생하지 않는 코드(강력보장)는 나중에 수행하자.
delete[] buff; // 예외가 없다.
buff = temp;
sz = s.sz; // 예외가 없다.
return *this;
}
};
void main()
{
String s1 = "hello";
String s2 = "A";
try
{
s1 = s2;
}
catch ( ... )
{
}
cout << s1 << endl; // 'A' 또는'hello" 가나와야한다.
}
class Stack
{
int buf[10];
int top;
public:
int Pop() throw( StackUnderflowException )
{
if ( top < 0 )
{
throw StackUnderflowException();
}
return buf[--top];
}
};
void main()
{
Stack s;
try
{
int n = s.Pop();
}
catch( StackUnderflowException e )
{
cout << "예외처리" << endl;
}
// 예외를 잡아서 문제를 처리했다. 이제 stack을 계속 사용할 수 있을까?
s.Push(10);
}