프로그래밍/C++

[C++] upcasting

갓똥 2019. 11. 26. 22:56
728x90
반응형

1. upcasting

class Shape {
public:
    int color;
};

class Rect : public Shape {
public:
    int x, y, w, h;
};

int main() {
    Rect rect;
    
    Rect*  p1 = ▭ // ok
    int*   p2 = ▭ // error
    Shape* p3 = ▭ // ??
    
    Shape& r = rect;   // ??
}

 

main함수를 살펴보자
1. Rect* p1 = ▭ 
  - 서로 똑같은 타입으로 아무 문제 없이 ok.
2. int* p2 = ▭
  - 이건 완벽히 다른 타입으로 error / 리인터프리터 캐스팅을 사용하면 가능
3. Shape* p3 = ▭
  - 앞에 포인터가 Rect는 아니지만 기반 클래스 타입인 경우는 어떨까?

p3의 주소를 따라가면 Shape가 있을 것이다.
해서 따라가면 Rect에 Shape가 있으므로 문제가 없음.

4. Shape& r = rect;
  - rect를 포인터가 아닌 참조로 가르킴. rect의 앞 부분에는 Shape가 있으므로 ok

  ① Up casting

    => 기반 클래스 타입의 포인터로 파생 클래스를 가리킬 수 있다.

    => 기반 클래스 타입의 참조로 파생 클래스를 가리킬 수 있다.

 


2. upcasting된 포인터의 사용

class Shape {
public:
    int color;
};

class Rect : public Shape {
public:
    int x, y, w, h;
};

int main() {
    Rect rect;
    
    Shape* p = ▭
    p->color = 0; // ok
    p->x = 0;     // ??
}

 

컴파일러는 Shape포인터로 생각하는데
p->color = 0; 의 경우 Shape의 멤버데이터 이므로 문제 없지만
p->x = 0; 의 경우 Shape가 없기 때문에 에러가 나게됨.
해결 방법은?
    static_cast<Rect*>(p)->x = 0;

  ① 기반 클래스 타입의 포인터로 파생 클래스를 가리킬 때

    => 기반 클래스의 멤버는 접근할 수 있지만

    => 파생 클래스가 추가한 멤버는 접근할 수 없다.

    => 파생 클래스가 추가한 멤버에 접근 하려면 포인터를 파생 클래스 타입으로 캐스팅해야 한다.

 


3. upcasting 활용

class Shape {
public:
    int color;
};

class Rect : public Shape {
public:
    int x, y, w, h;
};

void changeBlack(Rect* p) {
    p->color = 0;
}

int main() {
    Rect r;
    changeBlack(&r);
}

 

위의 코드에서 changeBlack함수는 인자로 받은 사각형의 색상을 검은색으로 바꿔주는 코드이다.
하지만 위 코드의 문제는 사각형만 바꿀 수 있다는 점이다.
Shape를 상속받을 Triangle, pentagon등이 추가된다면 그에 맞는 함수를 똑같이 또 만들어야한다.
void changeBlack(Shape* p) {
    p->color = 0;
}

  ① 동종 (동일한 기반 클래스를 사용하는 클래스)을 처리하는 함수를 만들 수 있다.

 

또한 도형을 보관하는 buffer를 만든다고 생각해봤을 때
Rect* buffer[10];의 경우 사각형만 보관할 수 있다. 이럴경우에는
    Rect* buffer[10];  // 사각형만 보관
    Shape* buffer[10]; // 모든 도형 보관

  ② 동종 (동일한 기반 클래스를 사용하는 클래스)을 보관하는 컨테이너를 만들 수 있다.

728x90
반응형