5월20일 C++(예외처리 try,catch,throw) API(멍때림)
2010. 5. 20. 13:08ㆍ2010년/5월
기본적으로 C++에서 컴파일까지 다끝난후.. 링킹까지 끝나서 실행파일이 만들어 졌을경우...
오류가 발생하는경우가 있다. 그경우 여러가지 이유가 있는데 메모리 참조문제.. 크기 문제...등
이런 예외적인 일이 발생한다 그경우 단지 윈도우 경고창을 볼수 있는데 그경우외에 다른 방법으로 오류메시지를 처리하는방법이 있다. 기본적으로 오류가 되는부분을 찾아야한다.
위와같은 오류 발생이 된다. 그 발생코드를 약간 변경시키는 경우를 보는것이 2가지이다.
throw와 try, catch()
일단 throw는 출력할 메시지를 말한다.
그래서
if(0>index)
{
throw "배열 범위를 초과하였음";
}
if(size<=index)
{
throw "배열 범위를 초과하였음";
}
통해서 오류부분을 메시지 출력으로 바꾸고
try부분은 바로 실행되는 부분이다. arr.SetAt(20,100)처럼 예외가 발생되는부분에
살짝 걸쳐두면된다.
그리고 마지막으로 catch()부분인데 이경우는 도스창에서 명령어를 띄우는것이다.
일반적으로 catch는 메시지를 받는부분이고 그 메시지는 catch의 인자로
문자열이기때문에 const char *를 사용하였다.
try와throw와 catch 대한 자세한내용이다.
■ try : 예외가 발생할만한 코드 블록을 지정하는데 try 다음의 { } 괄호안에 예외 처리 대상 코드를 작성한다. 이 블록 안에서 예외가 발생했을 때 throw 명령으로 예외를 던진다.
■ throw : 프로그램이 정상적으로 실행될 수 없는 상황일 때 이 명령으로 예외를 던진다. throw 다음에 던지고자 하는 예외를 적는다. 예외를 던진다는 것은 예외가 발생되었다는 것을 알리며 이 예외를 처리하는 catch문으로 점프하도록 한다. throw 명령 아래쪽의 코드들은 모두 무시되며 곧바로 예외 처리 구문으로 이동한다.
■ catch : try 블록 다음에 이어지며 던져진 예외를 받아서 처리한다. 그래서 catch 블록을 예외 핸들러라고 부른다. catch 다음에는 받고자 하는 예외의 타입을 적는데 이 객체는 throw에 의해 던져진다. catch 블록에는 예외를 처리하는 코드가 작성된다.
여기서 예외라는것은 아트메가에서 인터럽터와 비슷하게 생각하면된다.
보다시피 문자열로 보내는경우가 있고
class MyException
{
public:
const void *sender;
const char *description;
int info;
MyException(const void *sender,const char *description,int info)
{
this->sender=sender;
this->description=description;
this->info=info;
}
};
따로 클래스 만들어서 예외를 처리할수 있다.
throw에서 객체를 넘겨줄수도 있다.
throw MyException(this,"배열 범위를 초과하였음",index);
생성자에 맞게 인수를 전달하고
catch부문에서
catch(MyException T)
{
cout<<"객체주소:"<<T.sender<<endl;
cout<<"예외 내용:"<<T.description<<endl;
cout<<"부가정보:"<<T.info<<endl;
}
catch안 인수를 객체를 만들어 선언하고 하면된다.
#include<iostream>
using namespace std;
//객체지향 예외 처리(java도 흡사함)
class MyException
{
public:
const void *sender;
const char *description;
int info;
MyException(const void *sender,const char *description,int info)
{
this->sender=sender;
this->description=description;
this->info=info;
}
};
class outoRangeException:public MyException
{
public:
outoRangeException(const void *sender ,int index)
:MyException(sender,"배열 범위를 초과하였음",index)
{
}
};
class memoryException:public MyException
{
public:
memoryException(const void * sender,int index)
:MyException(sender,"해당 배열이 없음",index)
{
}
};
class DynamicArray
{
protected:
int *arr;
int size;
public:
DynamicArray(int arraySize)
{
arr=new int[arraySize];
size = arraySize;
}
~DynamicArray()
{
delete[] arr;
arr=0;
}
void SetAt(int index,int value)
{
if(0>index)
{
//throw "배열 범위를 초과하였음";
throw outoRangeException(this,index);
}
if(size<=index)
{
//throw "배열 범위를 초과하였음";
throw outoRangeException(this,index);
}
arr[index]=value;
}
int GetAt(int index) const
{
if(0>index)
{
//throw "배열 범위를 초과하였음";
throw memoryException(this,index);
}
if(size<=index)
{
//throw "배열 범위를 초과하였음";
throw memoryException(this,index);
}
return arr[index];
}
int GetSize() const
{
return size;
}
};
int main()
{
DynamicArray arr(10);
for(int i=0;10>i;++i)
{
arr.SetAt(i,(i+1)*10);
}
cout<<"Size of arry="<<arr.GetSize()<<endl;
for(i=9;0<i;--i)
{
cout<<"arr["<<i<<"]="<<arr.GetAt(i)<<endl;
}
try
{
arr.SetAt(2,100);
arr.SetAt(20,100);
}
catch(MyException &T)
{
cout<<"객체주소:"<<T.sender<<endl;
cout<<"예외 내용:"<<T.description<<endl;
cout<<"부가정보:"<<T.info<<endl;
}
try
{
arr.GetAt(2);
arr.GetAt(20);
}
catch(MyException &T)
{
cout<<"객체주소:"<<T.sender<<endl;
cout<<"예외 내용:"<<T.description<<endl;
cout<<"부가정보:"<<T.info<<endl;
}
return 0;
}
다음 throw와 catch의 관계에대해서이다
#include<iostream>
using namespace std;
void A();
void B();
void C();
int main()
{
try
{
A();
}
catch(int T)
{
cout<<"main()::catch:"<<T<<endl;
}
return 0;
}
void A()
{
cout<<"A()시작\n";
try
{
B();
}
catch(int ex)
{
cout<<"A():"<<ex<<endl;
throw;
}
}
void B()
{
cout<<"C()시작\n";
try
{
C();
}
catch(int ad)
{
cout<<"B():"<<ad<<endl;
throw;
}
}
void C()
{
cout<<"C()시작\n";
throw 100;
cout<<"C()끝\n";
}
각 함수는 다음 함수를 호출을 하고
마지막함수에 throw을 넣고 메인에 catch를 했다 그리고
다음함수 호출시에 try를 걸게 되면 어떻게 될까? 내생각대로라면 다 무시하고 갈줄알았는데
기본적으로 이전 함수catch로 단계별로돌아가는걸 볼수 있다.
throw에서 던질경우 catch가 받을수 있다.
근데 throw을 던질때타입이 객체이면 그 객체 맞게 catch간다. 하지만
만약에 throw 던질 타입이 아무것도 없다면 저렇게 catch(...)으로 표현할수있다
간단하게 if else문인데
catch부분이 else라고 보면 되고 if는 throw라고 보면된다.
그리고 괄호안은 다시 else if문의 조건이고
(...)인경우 그냥 else라고 할수 있다.
catch(outoRangeException &T) 대한 이야기
기본적으로 catch에서 참조하는경우
값전달과, 주소전달,포인터 경우가 있다.
값전달인경우 보내는 객체를 임시객체로 생성해서 어떻게 보면 생성자만 가져온다.
그래서 값을 전달하는경우와 받는경우 임시객체라서 사용후에 그 객체는 생성될 필요가없다.
하지만 값을 전달해버리면... 메모리에서 받는쪽과 전달하는쪽에 두군데 넣어야한다. 이런경우
어떻게 보면 메모리를 2배로 차지하게 된다.
그리고 *인경우 보내는 쪽은 주소를 보내야하고 실행할때 포인터연산도 해야 하며 그것을 받기위해
메모리 할당을 해야한다. 그래서 다시 메모리 해제라는 번거러움이 있다.
하지만 주소 참조는 일반적으로 alias다 즉 별칭이라서 기본적으로
아주 극단적으로
int a;
int b;
int *p=&a;
int &r=a;
*p=100;
r=200;
p=&b;
r=b;
주소참조는 값도 그리고 주소도받아버린다. 그리고 불러 쓰기까지한다.
그래서 객체지향에서는 기본적으로 최적화와 효율성에 의해서
대부분이 주소참조를 사용한다.
'2010년 > 5월' 카테고리의 다른 글
5월25일 C++(복사생성자,대입연산자,종속대입연산자.종속복사생성자,템플릿)API(simplepaint2) (0) | 2010.05.25 |
---|---|
5월24일 C++(SmartPointer,namespace,연산자오버로딩 API(대화상자 후반부) (0) | 2010.05.24 |
5월19일 C++(const, static,virtual,동적바인딩,순수가상함수 API(라디오박스,에디트박스,콤보박스) (0) | 2010.05.19 |
5월18일 C++(pragma pack(1) 패딩,API(그래픽 DC 간략한정보,폰트 7장컨트롤) (0) | 2010.05.18 |
5월17일 C++(PCAP),API() (0) | 2010.05.17 |