티스토리 뷰

*다향성(Pholymophism)

는 객체간의 결합(coupling)을 약하게 만들어서, 객체 간의 연결을 유연하게 해줍니다.(Virtual Function 이용)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
using namespace std;
class Parent {
public : 
    int val = 1;
가상함수
    virtual void function() {
        cout << val << endl;
    }
};
 
class Child_2 :public Parent {
public :
    void function()
    {
        cout << val * << endl;
    }
};
 
class Child_3 :public  Parent {
public:
    void function()
    {
        cout << val * << endl;
    }
};
 
int main()
{
    Parent *p[3= { NULL };
    p[0= new Parent;
    p[1= new Child_2;
    p[2= new Child_3;
 
    for (int i = 0; i < 3; i++) {
        p[i]->function();
    }
}
cs


virtual void function()에서 virtual 키워드를 제거하였을 때 모두 1이 출력됩니다.(=Parent의 function()이 출력)


*순수가상함수

1
2
3
4
5
class Parent {
public : 
    int val = 1;
순수가상함수
    virtual void function() = 0;
};
cs

virtual void function() = 0;와 같이 순수가상함수를 포함하는 class를 추상class라고 지칭하며,

추상class는 객체 생성이 불가능 합니다.

(Abstract class <-> Concrete Class)

순수가상함수의 경우, 함수의 내용을 구현하지않아도 컴파일오류가 뜨지 않습니다.


*오버로딩과 오버라이딩

정상적인 실행

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Parent {
public : 
    int val = 1;
    void function() {
        cout << val<<endl;
    }
    void function(int n) {
        val = n;
        cout << val<<endl;
    }
};
 
class Child :public Parent {
public :
    //void function();
};
 
int main()
{
    Child c;
    c.function();
    c.function(5);
}
cs

부모클래스에서 오버로딩된 함수 중 하나라도 오버라이딩 한다면, 나머지 함수는 사용할 수 없습니다.

1
2
3
4
class Child :public Parent {
public :
    void function();
};
cs

Child에서 function()을 오버라이딩했으므로 Parent의 function()과 오버로딩된 function(int n)은 사용할 수 없습니다.


*예외 객체의 사용

다양한 정보를 함께 throw할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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 DynamicArray {
protected:
    int size;
    int *arr;
public :
    DynamicArray(int size) { 
        this->size = size;
        arr = new int[this->size];
    }
    ~DynamicArray() {
        delete[] arr;
    }
 
    void SetAt(int index, int value) {
        if (index < || GetSize() <= index) {
            throw MyException(this"Out of Range", index);
        }
        arr[index] = value;
    }
    int GetAt(int index) const {
        return arr[index];
    }
    int GetSize() const {
        return size;
    }
};
 
int main()
{
    DynamicArray da(5);
    try {
        da.SetAt(56);
    }
 
    catch(MyException &e){
        cout <<"error message : "<< e.description<<endl<<
            "information : "<<e.info<<endl;
    }
}
cs

추가로, 다형성을 사용하여 예외에대한 관리를 할 수 있습니다.

1
2
3
class OutOfRangeException : public MyException
class MemoryException : public  MyException
 
cs


*예외처리 규칙

함수를 건너서 throw할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void B() {
    throw "Exception";
}
 
void A()
{
    B();
}
 
int main()
{
    try {
        A();
    }
    catch (char *ex) {
        cout << ex << endl;
    }
}
cs


A에서 B의 throw를 받아 catch, 다시 throw하여 main에서 catch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void B() {
    throw "Exception";
}
 
void A()
{
    try {
        B();
    }
    catch (char *ex) {
        cout << "A : " << ex<<endl;
        throw;
    }
}
 
int main()
{
    try {
        A();
    }
    catch (char *ex) {
        cout <<"main() : "<< ex << endl;
    }
}
cs


try문 하나에 여러 개의 catch문이 올 수 있습니다.

단, 중간에 catch가 일어나면 해당 catch문에서 exception이 끝납니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
try
    {
        A();
    }
    catch(MemoryException& ex)
    {
        cout << "MemoryException 타입으로 잡혔음\n";
    }
    catch(OutOfRangeException& ex)
    {
        cout << "OutOfRangeException 타입으로 잡혔음\n";
    }
    catch(...)
    {
        cout << "그 밖의 타입\n";
    }
 
cs


불필요한 복사를 줄이기 위하여 예외객체는 레퍼런스로 받는 것이 좋습니다.

1
2
3
4
 catch(MyException &e){
        cout <<"error message : "<< e.description<<endl<<
            "information : "<<e.info<<endl;
    }
cs


*리소스 정리

소멸자에서의 정리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Delete_resource {
public :
    Delete_resource(char *p) :ptr(p) {};
    ~Delete_resource() {
        delete[] ptr;
    }
 
private : 
    char *ptr;
};
int main()
{
    try {
        char *= new char[100];
        Delete_resource dr(p);
        throw "Exception";
    }
    catch (char * ex) {
        cout << ex << endl;
    }
}
cs


*생성자, 소멸자에서의 정리

생성자에서 예외가 발생한 경우 : 객체가 생성되지 않은 것 = 소멸자 호출되지 않음!

예외는 그대로 던진다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Delete_resource(int arraySize) {
        try
        {
            // 동적으로 메모리를 할당한다.
            arr = new int[arraySize];
            size = arraySize;
            throw MemoryException(this0);
        }
        catch (...)
        {
            cout << "여기는 실행된다!!\n";
 
            delete[] arr;    // 리소스를 정리한다.
 
            throw;        // 예외는 그대로 던진다.
        }
    }
cs


소멸자에서 예외가 발생한 경우 : 프로그램이 비정상 종료할 수 있으므로 소멸자 밖으로 throw되지 않게 한다

1
2
3
4
5
6
7
8
9
10
11
12
13
DynamicArray::~DynamicArray()
{
    try
    {
        // 메모리를 해제한다.
        delete[] arr;
        arr = 0;
    }
    catch(...)
    {
    }
}
 
cs


*bad_alloc

동적메모리 할당이 실패한 경우를 catch합니다.

1
2
3
4
5
6
try {
        char *= new char[0x7ffffff0];
    }
    catch (bad_alloc &ex) {
        cout << ex.what()<<endl;
    }
cs

* new, new[] 연산자를 사용하는 코드에서는 bad_alloc이 throw될 수 있다고 가정해야한다.

*auto_ptr

1
2
3
4
5
6
7
#include <memory>
using namespace std;
 
int main()
{
    auto_ptr<int> ptr(new int);
}
cs

#include <memory>

using namespace std;

를 사용해야하며, auto_ptr로 선언된 포인터는 자동으로 해제된다.


스파게티코드 : 코드가 꼬여있는 것

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함