[C++] 디자인패턴 : uscasting
upcasting
기반 클래스 타입의 포인터(참조)로 파생 클래스 객체를 가리킬 수 있다.
class Animal
{
int age;
};
class Dog : public Animal
{
int color;
};
int main()
{
Dog d;
Dog* p1 = &d; // ok.
double* p2 = &d; // error.
Animal* p3 = &d; // ok.
}
Dog 형태의 d 는 age, color를 가지고 있다.
Animal p3에를 메모리를 찾아가면 age 존재하기 때문에 문제가 없다.
폴더와 파일의 관계를 생각해볼 수 있다.
폴더는 폴더 안에 폴더와 파일을 가질 수 있다.
그래서 폴더와 파일을 동시에 가질 수 있는 기반 객체 Item을 만들어 둘 다 허용할 수 있다.
즉, Folder에 File뿐 아니라 Folder도 보관하려면 File과 Folder는 공통의 기반 클래스 Item이 있어야 한다.
upcasting 과 virtual
아래 코드의 Cry()는 virtual이 없다. 즉 가상 함수가 아니다.
이런 경우 p->Cry();를 호출했을 때 아래의 결과 처럼 Animal Cry가 출력된다.
#include <iostream>
using namespace std;
class Animal
{
int age;
public:
void Cry() { cout << "Animal Cry" << endl;}
};
class Dog : public Animal
{
int color;
public:
void Cry() { cout << "Dog Cry" << endl;}
};
int main()
{
Dog d;
Animal* p = &d;
p->Cry();
}
아래 처럼 Animal 기반 클래스의 Cry()가 virtual 형태인 가상 함수로 정의가 되어 있다면
아래의 결과 처럼 Dog Cry로 출력된다.
가상 함수 룰에 따라 파생 클래스로 호출됨을 알 수 있다.
#include <iostream>
using namespace std;
class Animal
{
int age;
public:
virtual void Cry() { cout << "Animal Cry" << endl;}
};
class Dog : public Animal
{
int color;
public:
// override
virtual void Cry() { cout << "Dog Cry" << endl;}
};
int main()
{
Dog d;
Animal* p = &d;
p->Cry();
}
간단하지만 대형 코드를 접하다 보면 이런 사소한 부분 때문에 이해가 잘 안되는 경우가 더러 생긴다.
그만큼 기초가 중요한 이유라고 할 수 있겠다.
기반 클래스 포인터로 파생 클래스를 가리 킬 때
- 파생 클래스가 재정의 한 함수가 호출되게 하려면 반드시 가상 함수로 만들어야 한다.
'C++' 카테고리의 다른 글
[C++] 디자인 패턴 : 변하는 것을 분리하는 방법 2가지 (0) | 2022.01.30 |
---|---|
[C++] 디자인패턴 : protected constructor (0) | 2022.01.27 |
[C++] Design Patterns (디자인 패턴) - GoF (0) | 2022.01.26 |
[C++] exception (예외처리) (0) | 2022.01.10 |
[C++] cout, endl 원리, operator<< 재정의 (0) | 2022.01.02 |
댓글