fullstack

'전체 글'에 해당되는 글 76건

  1. [C++] 연산자 오버로딩
  2. [C++] 다중 상속 1
  3. [C++] virtual 소멸자

[C++] 연산자 오버로딩

Language/C++

연산자 오버로딩은 일종의 C++와의 약속이다. operator라는 키워드와 연산자 기호를 묶어서 함수 이름을 정의하면 연산자를 이용해 함수를 호출하는 셈이다.

즉, p+10이라는 문장이 있고, p가 객체라면 p.operator+(10) 이라는 문장으로 해석하여 오버로딩한 함수를 호출하게 되는 것이다.


다음은 간단한 연산자 오버로딩의 예제이다.


1
2
3
4
5
6
7
8
9
10
11
class Point {
private:
    int x, y;
public:
    Point(int _x=0int _y=0) : x(_x), y(_y) {}
    Point operator+(int val);
};
Point Point::operator+(int val) {
    x+=val;
    y+=val;
}



위와 같이 연산자 오버로딩을 하면 다음과 같이 간단한 방법으로 포인트 객체의 x, y값을 한번에 증가시킬 수 있다.


1
2
Point p;
p+10;



'Language > C++' 카테고리의 다른 글

[C++] 템플릿 (Template)  (0) 2016.01.10
[C++] 임시 객체  (0) 2016.01.04
[C++] 다중 상속  (1) 2015.12.28
[C++] virtual 소멸자  (0) 2015.12.26
[C++] 순수 가상 함수와 추상 클래스  (0) 2015.12.26

[C++] 다중 상속

Language/C++

다중 상속이란 하나의 Derived 클래스가 둘 이상의 Base 클래스를 상속하는 것을 말한다.

다음과 같이 콤마 연산자로 사용할 수 있다.


1
class CCC : public AAA, public BBB



다중 상속은 유용한 문법이 아니다. 클래스의 관계를 복잡하게 만들기 때문에 사용하지 않는 것이 좋다.


아래는 다중 상속을 사용할 때 발생할 수 있는 문제점이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class AAA
{
public:
    void func() { cout << "AAA" << endl; }
};
 
class BBB
{
public:
    void func() { cout << "BBB" << endl; }
};
 
class CCC : public AAA, public BBB
{
public:
    void print() {
        func(); // error
    }
};



위 예제는 다중 상속을 사용했을 때 발생할수 있는 에러이다.

CCC 클래스는 AAA 클래스와 BBB 클래스를 상속하였는데 두 클래스에 같은 이름의 멤버 함수가 있다면 이처럼 모호성이 발생한다.

컴파일러는 func 함수가 AAA 클래스에 있는 것을 말하는 건지 BBB 클래스에 있는 것을 말하는 건지 모호하여 에러를 출력하였는데, 이는 AAA::func() 혹은 BBB::func() 이런 식으로 클래스를 알려주면 컴파일이 가능하다.




다음은 또다른 문제점 이다.


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
class AAA
{
public:
    void func1() { cout << "AAA" << endl; }
};
 
class BBB : public AAA
{
public:
    void func2() { cout << "BBB" << endl; }
};
 
class CCC : public AAA
{
public:
    void func3() { cout << "CCC" << endl; }
};
 
class DDD : public BBB, public CCC
{
public:
     void print() {
         func1(); // error
    }
};




BBB 클래스와 CCC 클래스 둘다 AAA 클래스를 상속하고 있고, DDD 클래스는 BBB 클래스와 CCC 클래스를 다중 상속하고 있다.

아래 그림 처럼 다중 상속이 다이야몬드 형태로 구조가 나타날때도 모호성이 발생한다.



BBB 클래스와 CCC 클래스 둘다 AAA 클래스를 상속하였기 때문에 이 둘을 다중 상속하게되면 AAA 클래스를 중복으로 상속하게 되는 것이다. 때문에, AAA 클래스의 멤버 함수를 두 개 지니게 되고, 모호성이 발생하여 에러가 발생하게 된다.

이는, AAA 클래스가 DDD 클래스에 한번만 상속되도록 하는 virtual 상속을 사용하여 해결할 수 있다.


1
class BBB : virtual public AAA



1
class CCC : virtual public AAA



이렇게 BBB 클래스와 CCC 클래스에서 virtual 상속을 하게되면 이 두 클래스를 다중상속 하더라도 AAA 클래스 안에 존재하는 멤버들은 한번만 상속이 이루어 진다.




이처럼 다중상속의 문제점을 해결할 수는 있지만, 어쨋든 다중 상속을 사용하면 클래스들 간에 관계가 복잡해지므로 사용하지 않는 것이 좋다.



'Language > C++' 카테고리의 다른 글

[C++] 임시 객체  (0) 2016.01.04
[C++] 연산자 오버로딩  (0) 2016.01.04
[C++] virtual 소멸자  (0) 2015.12.26
[C++] 순수 가상 함수와 추상 클래스  (0) 2015.12.26
[C++] static binding & dynamic binding  (0) 2015.12.26

[C++] virtual 소멸자

Language/C++

이전 글인 [C++] virtual 키워드 에서 virtual 키워드로 가상함수를 만든다는 것을 알았다.

하지만 virtual 키워드를 붙여 주어야 할 대상은 가상함수 뿐만이 아니다. 소멸자 앞에 virtual 키워드를 붙인 것을 virtual 소멸자라 한다.

그럼 virtual 소멸자는 왜 써야할까? 다음 예제를 보자

 

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
#include <iostream>
using namespace std;
 
class AAA
{
public:
    AAA() { cout << "AAA()" << endl; }
    ~AAA() { cout << "~AAA()" << endl; }
};
 
class BBB : public AAA
{
public:
    BBB() { cout << "BBB()" << endl; }
    ~BBB() { cout << "~BBB()" << endl; }
};
 
int main()
{
    AAA* b = new BBB;
 
    delete b;
 
    return 0;
}




위의 예제를 보면 AAA 타입의 포인터로 BBB 객체를 생성하였다. 그리고 해당 객체를 소멸하자 AAA 클래스의 소멸자만 호출이 되었다.

이는 소멸할 객체는 BBB 객체이지만 AAA 타입의 포인터로 가리키고 있기 때문에, 컴파일러는 AAA 객체로 인식한 것이다.


이를 해결하기 위해서 다음과 같이 Base 클래스의 소멸자에 virtual 키워드를 붙여주면 모든 소멸자가 올바르게 출력되는 것을 볼 수 있다.


1
virtual ~AAA() { cout << "~AAA()" << endl; }



이렇게 하면 Base 클래스의 소멸자를 호출하려다 virtual 인 것을 보고, Derived 클래스의 소멸자를 호출하게 된다.

그 다음으로 BBB 클래스의 소멸자는 AAA 클래스를 상속하고 있기 때문에 다시 AAA 클래스이 소멸자가 호출되게 된다.


'Language > C++' 카테고리의 다른 글

[C++] 연산자 오버로딩  (0) 2016.01.04
[C++] 다중 상속  (1) 2015.12.28
[C++] 순수 가상 함수와 추상 클래스  (0) 2015.12.26
[C++] static binding & dynamic binding  (0) 2015.12.26
[C++] virtual 키워드  (0) 2015.12.24