[C++] 상속에서의 형변환 - 업캐스팅(Upcasting)

2024. 6. 27. 23:50·Programming Language(Sub)/C++

상속에서의 형변환 - 업캐스팅(Upcasting)

Based *b = new Derived;
  • 우리는 위와 같이 자식 클래스의 객체를 가리켜왔다. 이게 가능한 이유가 업 캐스팅(Upcasting) 때문이다.

  • double a = 1이 가능한 이유는 double a = (double)1; 이라는 묵시적 변환이 이루어졌기 때문이다.

int main() {
    Derived *d = new Derived;
        Base *b = d;
}
  • 위와 같이 자식 클래스에서 부모 클래스로 올라가는 형태의 캐스팅을 업 캐스팅(Upcasting)이라고 한다

  • Upcasting: 자식 클래스 포인터 -> 부모 클래스 포인터(묵시적)

    • 총각은 남자가 되도 문제가 없지만, 남자가 총각인 것은 아니다.

    • 그래서 자식 클래스 포인터(총각)를 부모 클래스 포인터(남자)로 묵시적으로 변환해도 문제가 없다.

  • 업캐스팅이 항상 문제가 없는 것은 아니다. 다음 예시를 확인해보자

#include <iostream>
using namespace std;
class Animal {
   public:
    float xpos = 1; // 초기값 1
    float ypos = 2; // 초기값 2
};

void printAnimals(Animal a[], int n) {
    for (int i = 0; i < n; i++) {
        cout << "(" << a[i].xpos << ", " << a[i].ypos << ")" << endl;
    }
}

int main(void) {
    Animal *a = new Animal [10];  
    printAnimals(a, 10);
        delete[] a;
}
  • 여기까지는 문제가 없다.

  • FlyingAnimal이라는 클래스를 만들었다고 해보자

class FlyingAnimal : public Animal {
   public:
    float zpos = 3;
};

void printAnimals(Animal *a, int n) {
    for (int i = 0; i < n; i++) {
        cout << "(" << a[i].xpos << ", " << a[i].ypos << ")" << endl;
    }
}

int main() {
        FlyingAnimal *a = new FlyingAnimal[10];  
    printAnimals(a, 10);
        delete[] a;
}
  • printAnimals(a, 10)에서 업캐스팅이 일어날 것으로 예상할 수 있다. 실행을 해보자

  • 실행 결과

(1, 2)
(3, 1)
(2, 3)
(1, 2)
(3, 1)
(2, 3)
(1, 2)
(3, 1)
(2, 3)
(1, 2)

  • 컴파일 에러는 발생하지 않았는데 왜 이런일이 발생했을까?

    • 본질적으론 함수를 잘못 사용해서 이런 일이 발생했다.
  • Animal은 x, y를 가지고 있고, FlyingAnimal은 x, y, z를 가지고 있다.

    • Animal은 8바이트 크기를 가지고, FlyingAnimal은 12바이트 크기를 가지게 된다.
    • FlyingAnimal a = new FlyingAnimal[10]에서 12\10 바이트 크기의 배열을 만들었다

      • printAnimal(a, 10);에서 a가 Animal로 묵시적 형변환이 일어난다.

        • Animal은 하나당 8바이트의 크기를 가지고 있다.

        • 그래서 x, y, z, x, y, z....에서 a[0]: (x, y), a[1]: (y, z), a[2]: (z, y), a[3]: (x, y)... 이런 식으로 된다

  • Solution: 포인터 배열을 사용해서 해결해주면 된다

int main(void) {
    Animal **a = new Animal*[10];  // 포인터배열, Flying Animal을 가리키는 포인터들의 배열을 만들자.(배열에는 flying animal의 주소를 가지고 있음.)
}
  • Animal *a = new Animal\[10];

    • Animal의 주소를 담을 수 있는 10칸짜리 배열이다.

      • 배열의 한 칸은, Animal의 주소(Animal*)를 담고 있다.

      • 그리고 이 Animal을 가리키는 또 다른 타입은 Animal*이 된다

void printAnimals(Animal **a, int n) {
    for (int i = 0; i < n; i++) {
        cout << "(" << a[i]->xpos << ", " << a[i]->ypos << ")" << endl;
    }
}

int main(void) {
    Animal **a = new Animal*[10];
    for (int i = 0; i < 10; i++) {
        a[i] = new FlyingAnimal;
    }
    printAnimals(a, 10);
    // 부모 포인터가 자식 포인터를 가리키면 배열에서 문제가 발생함.
    for (int i = 0; i < 10; i++) {
        delete a[i];
    }
    delete[] a;
}
  • for문 내부

    • Animal의 주소를 담을 수 있는 각 배열의 칸에 FlyingAnimal 객체를 가리키도록 해준다

      • 그리고 각 칸마다 FlyingAnimal 객체 하나씩을 생성해줬으므로, 각 칸이 가리키는 메모리를 해제해줘야 한다
  • 이렇게 포인터 배열을 이용하여 수정하면 제대로 작동하게 된다

    • FlyingAnimal 객체 10개를 연속해서 저장한게 아니라, 포인터 배열을 통해서 객체 10개를 따로 생성한 후 가리켰기 때문에, 처음에 말했던 오류가 발생하지 않게 되는 것이다.

    • C++ STL을 사용하면 이런 번잡함을 줄일 수 있다. (추후 다룰 예정)

'Programming Language(Sub) > C++' 카테고리의 다른 글

[C++] 상속에서의 형변환 - RTTI와 dynamic_cast  (0) 2024.06.28
[C++] 상속에서의 형변환 - 다운캐스팅  (0) 2024.06.27
[C++] 생성/소멸자 실행 순서와 가상 소멸자  (0) 2024.06.27
[C++] 순수 가상 함수와 추상 클래스  (0) 2024.06.27
[C++] 상속이 필요한 이유(2)  (0) 2024.06.27
'Programming Language(Sub)/C++' 카테고리의 다른 글
  • [C++] 상속에서의 형변환 - RTTI와 dynamic_cast
  • [C++] 상속에서의 형변환 - 다운캐스팅
  • [C++] 생성/소멸자 실행 순서와 가상 소멸자
  • [C++] 순수 가상 함수와 추상 클래스
lumana
lumana
배움을 나누는 공간 https://github.com/bebeis
  • lumana
    Brute force Study
    lumana
  • 전체
    오늘
    어제
    • 분류 전체보기 (463)
      • 개발 일지 (0)
        • Performance (0)
        • TroubleShooting (0)
        • Refactoring (0)
        • Code Style, Convetion (0)
        • Architecture (0)
      • Software Engineering (36)
        • Test (8)
        • 이론 (18)
        • Clean Code (10)
      • Java (72)
        • Basic (5)
        • Core (21)
        • Collection (7)
        • 멀티스레드&동시성 (13)
        • IO, Network (8)
        • Reflection, Annotation (3)
        • Modern Java(8~) (13)
        • JVM (2)
      • Spring (53)
        • Framework (12)
        • MVC (23)
        • Transaction (3)
        • AOP (11)
        • Boot (0)
        • AI (0)
      • DB Access (16)
        • Jdbc (1)
        • JdbcTemplate (0)
        • JPA (14)
        • Spring Data JPA (0)
        • QueryDSL (0)
      • Computer Science (130)
        • Data Structure (27)
        • OS (14)
        • Database (10)
        • Network (21)
        • 컴퓨터구조 (6)
        • 시스템 프로그래밍 (23)
        • Algorithm (29)
      • HTTP (8)
      • Infra (1)
        • Docker (1)
      • 프로그래밍언어론 (15)
      • Programming Language(Sub) (77)
        • Kotlin (1)
        • Python (25)
        • C++ (51)
        • JavaScript (0)
      • FE (11)
        • HTML (1)
        • CSS (9)
        • React (0)
        • Application (1)
      • Unix_Linux (0)
        • Common (0)
      • PS (13)
        • BOJ (7)
        • Tip (3)
        • 프로그래머스 (0)
        • CodeForce (0)
      • Book Review (4)
      • Math (3)
        • Linear Algebra (3)
      • AI (7)
        • DL (0)
        • ML (0)
        • DA (0)
        • Concepts (7)
      • 프리코스 (4)
      • Project Review (6)
      • LegacyPosts (11)
      • 모니터 (0)
      • Diary (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
lumana
[C++] 상속에서의 형변환 - 업캐스팅(Upcasting)
상단으로

티스토리툴바