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

2024. 6. 27. 23:50·Programming Language/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 > 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/C++' 카테고리의 다른 글
  • [C++] 상속에서의 형변환 - RTTI와 dynamic_cast
  • [C++] 상속에서의 형변환 - 다운캐스팅
  • [C++] 생성/소멸자 실행 순서와 가상 소멸자
  • [C++] 순수 가상 함수와 추상 클래스
lumana
lumana
배움을 나누는 공간 https://github.com/bebeis
  • lumana
    Brute force Study
    lumana
  • 전체
    오늘
    어제
    • 분류 전체보기
      • Spring
        • MVC
        • DB
        • 핵심 원리
        • JPA
      • WEB
        • HTML
        • CSS
        • HTTP
        • Application
      • Computer Science
        • Network
        • Database
        • OS
        • 시스템 프로그래밍
        • 컴퓨터구조
      • Algorithm
        • Divide&Conquer
        • Sort
        • Greedy
        • DP
        • Backtracking
        • NP-Complete
        • Graph
      • Data Structure
        • 자료구조
        • C++ STL
        • Java Collection
      • 소프트웨어 공학
        • 시험 공부 정리
        • Theorem
      • Programming Language
        • Python
        • Java
        • C
        • C++
        • Rust
        • Theory
      • Unix_Linux
        • Common
      • React
      • PS
        • BOJ
        • Tip
        • 프로그래머스
        • CodeForce
      • Book Review
        • Clean Code
      • Math
        • Linear Algebra
      • AI
        • DL
        • ML
        • DA
        • Concepts
      • 우아한테크코스
        • 프리코스
      • Project Review
      • LegacyPosts
      • Android
      • Apple
        • Mac
        • IPhone
        • IPad
      • 모니터
      • Diary
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

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

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.