Date: 2026.08.20
오늘 배운 것
- Unreal C++에서 아이템 클래스의 상속 구조 구현
- ActorHasTag("Player")를 이용한 플레이어 판별
- GEngine->AddOnScreenDebugMessage()를 이용한 디버깅
- 부모 클래스의 함수를 자식 클래스가 상속받아 사용하는 과정
- virtual과 override의 관계
- 자식 클래스에서 함수를 재정의하면 부모의 기능이 가려질 수 있다는 것
- 공통 기능은 부모 클래스에 작성하고, 자식 클래스에서는 필요한 값만 변경하는 구조
1. 아이템 클래스의 기본 상속 구조
오늘 만든 아이템 구조는 다음과 같다.
│
├── AMineItem
│
├── AHealingItem
│
└── ACoinItem
│
├── ABigCoinItem
│
└── ASmallCoinItem
BaseItem을 가장 상위 부모 클래스로 두고,
- 지뢰
- 회복 아이템
- 코인
을 각각 자식 클래스로 만들었다.
그리고 코인은 다시:
- BigCoin
- SmallCoin
으로 한 단계 더 상속했다.
2. HealingItem 구현
AHealingItem에는 회복량을 저장할 변수로 HealAmount를 만들었다.
생성자에서 기본값을 설정했다.
처음에는 ActivateItem()에서 단순히 아이템만 삭제했다.
이후 실제 기능을 구현하기 전에 아이템이 정상적으로 활성화되는지 확인하기 위해 디버그 메시지를 추가했다.
여기서 HealAmount가 float이므로 %d가 아니라 %.0f를 사용했다.
3. FString::Printf()의 형식 지정자 문제
처음에는 다음과 같이 작성했다.
그런데 컴파일 과정에서 C7595 오류가 발생했다.
원인은 ExplosionDamage가 float인데 %d를 사용했기 때문이다.
따라서:
처럼 수정했다.
이 과정을 통해 문자열 안의 포맷 지정자와 실제 전달하는 변수의 타입이 맞아야 한다는 것을 확인했다.
4. CoinItem 구현
코인은 ACoinItem을 부모로 두고 BigCoin과 SmallCoin을 자식으로 만들었다.
코인마다 획득하는 점수가 다르므로:
를 만들었다.
그리고 CoinItem.cpp에서는 공통적인 코인 기능을 구현했다.
여기서:
를 통해 현재 아이템을 활성화시킨 Actor가 플레이어인지 확인했다.
5. BigCoin에서 부모 기능을 상속받도록 수정
BigCoin에서는 생성자에서 점수만 다르게 설정했다.
처음에는 BigCoin에도 다음 코드가 있었다.
그리고 .cpp에는:
가 있었다.
그런데 이렇게 하면 BigCoin이 ACoinItem의 ActivateItem()을 사용하는 것이 아니라 자기 자신의 ActivateItem()을 실행한다.
따라서:
만 실행되고,
부모인 ACoinItem의:
메시지는 실행되지 않았다.
6. 트러블슈팅 — 왜 String이 안 떴을까?
문제 상황:
처음에는 Overlap 자체의 문제라고 생각할 수도 있었지만, 아이템이 정상적으로 Destroy되는 것을 통해 Overlap과 ActivateItem() 자체는 실행되고 있다는 것을 확인했다.
결국 BigCoin에 있던:
이 원인이었다.
이 함수가 존재하기 때문에 BigCoin은 부모의 ActivateItem()을 사용하지 않고 자기 자신의 함수를 실행하고 있었던 것이다.
7. virtual / override를 직접 이해한 순간
BigCoin의 ActivateItem()을 삭제하고,
헤더의:
도 삭제했다.
그러자 BigCoin이 부모인 ACoinItem의 ActivateItem()을 그대로 사용하기 시작했다.
BigCoin에서는:
만 설정되어 있으므로 부모의 함수가 실행될 때:
의 PointValue에 50이 들어갔다.
결과:
정상적으로 출력됐다.
8. 오늘 가장 중요했던 이해
이번 과정을 통해 단순히
"virtual은 가상 함수다."
라고 외우는 것보다 실제로 부모와 자식의 함수를 비교하면서 이해할 수 있었다.
현재 구조는:
이렇게 구성할 수 있다.
즉 공통적인 기능은 부모 클래스에 작성하고, 자식 클래스에서는 자신에게 필요한 값만 변경하면 된다.
그래서 BigCoin과 SmallCoin에 똑같은 ActivateItem() 코드를 복붙할 필요가 없다.
💡 오늘의 핵심 정리
virtual
부모 클래스에서:
라고 선언하면 자식 클래스가 이 함수를 재정의할 수 있도록 열어두는 것이다.
override
자식 클래스에서:
라고 하면 부모의 virtual 함수를 자식이 자기 방식으로 재정의한다는 의미다.
그리고 중요한 것은:
자식에서 함수를 override하면 부모의 함수가 자동으로 같이 실행되는 것이 아니다.
자식 함수가 실행되기 때문에 부모 함수의 기능이 필요하다면 별도로 처리해야 한다.
반대로 자식에서 ActivateItem() 자체를 만들지 않으면 부모의 구현을 그대로 물려받아 사용할 수 있다.
🧠 오늘 얻은 가장 큰 깨달음
처음에는 상속 구조를:
"부모 → 자식으로 코드를 물려준다."
정도로 생각했는데, 오늘 직접 코드를 수정하면서 조금 더 구체적으로 이해하게 되었다.
특히 BigCoin의 문제를 해결하면서
라는 흐름을 직접 경험했다.
오늘은 virtual과 override를 문법으로 외운 게 아니라 실제 트러블슈팅을 통해 이해한 날이었다.