다중상속
다중상속을 하면 C가 A에게 상속받은 변수를 사용하려고 해도 B1이 A에게 상속받은 변수인지 B2가 A에게 상속받은 변수인지 알수가 없기에 문제가 생긴다. 해결방법은 가상상속이 있으나 제일 좋은건 다중상속을 사용 안하는것이다.
- 여러 부모 클래스: 다중상속을 사용하면 하나의 자식 클래스가 여러 부모 클래스로부터 상속을 받을 수 있습니다. 이로 인해 자식 클래스는 여러 부모 클래스의 특성과 메서드를 모두 가질 수 있습니다.
- 다이아몬드 문제: 다중상속을 사용할 때 발생할 수 있는 문제 중 하나로 다이아몬드 문제(Diamond Problem)가 있습니다. 이 문제는 하나의 클래스가 두 개 이상의 부모 클래스로부터 상속받고, 이 부모 클래스들이 공통으로 같은 메서드나 속성을 가질 때 발생하는 모호성을 해결하는 문제입니다. 이러한 모호성을 해결하기 위해 언어마다 다른 방식의 규칙이나 해결 방법이 존재합니다.
- 복잡성 증가: 다중상속을 남용하면 코드의 복잡성이 증가할 수 있으며, 클래스 간의 관계를 이해하기 어려울 수 있습니다. 따라서 다중상속을 사용할 때는 신중하게 고려하고 설계해야 합니다.
인터페이스
C++에서 Interface를 부모클래스로 하는 PosableOneInterface생성후 GPCCharacter에서 사용을 할것인데 위의 사진처럼 BP에서 인터페이스 적용시키는걸 C++에서 적용시키는 것이다.
#include "PosableOneInterface.h" //인터페이스의 내용을 알아야하니 헤더파일 추가
UCLASS(Abstract) // GPCCharacter 클래스로 인스턴스를 생성 안할거니 UCLASS(Abstract)추가
class GPC_CPP_12_API AGPCCharacter:
public ACharacter,
public IPosableOneInterface
//이때 인터페이스를 상속시켜 다중상속이 발생하지만 인터페이스의 내부함수들은 순수가상함수만
//사용할것이라 오류가 발생하지않는다.
{
};
Interface생성
class GPC_CPP_12_API IPosableOneInterface
{
GENERATED_BODY()
// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
virtual void BeginPoseA() PURE_VIRTUAL(IPosableOneInterface::BeginPoseA)
virtual void BeginPoseB() PURE_VIRTUAL(IPosableOneInterface::BeginPoseB)
virtual void EndPoseA() PURE_VIRTUAL(IPosableOneInterface::EndPoseA)
virtual void EndPoseB() PURE_VIRTUAL(IPosableOneInterface::EndPoseB)
};
블루프린트에서는 인터페이스는 그저 알림같은 용도로 사용되고 인터페이스 자체로 기능을 구현할수없었는데 C++에서는 기본 구현도 가능해서 생성할때 h파일말고 cpp파일도 생성이 된다.
인터페이스는 순수가상함수를 사용해야 다중상속을 해도 문제가 없기에 순수가상함수만을 사용할것이다.
C++에서는 순수가상함수를 쓸때 함수명 뒤에 = 0;나 abstract를 붙여 사용하지만 언리얼에서는 이 방식을 사용할때
인스턴스 생성이 막히기에 PURE_VIRTUAL(클래스명::함수명)을 붙여 사용한다.
class GPC_CPP_12_API AGPCPlayerController:
public APlayerController,
public IPosableOneInterface
{
GENERATED_BODY()
protected:
void SetupInputComponent() override;
#pragma region IPosableOneInterface //#pragma region 이름으로 영역을 만들수있고 endregion으로 닫는다.
private:
void BeginPoseA() override;
void BeginPoseB() override;
void EndPoseA() override;
void EndPoseB() override;
#pragma endregion
};
PosableOneInterface에서 가져온 함수들을 오버라이드 시킨다.
Interface 정의
void AGPCPlayerController::BeginPoseA()
{
if (auto const PosableOne = Cast<IPosableOneInterface>(GetPawn()))
PosableOne->BeginPoseA();
}
void AGPCPlayerController::BeginPoseB()
{
if (auto const PosableOne = Cast<IPosableOneInterface>(GetPawn()))
PosableOne->BeginPoseB();
}
void AGPCPlayerController::EndPoseA()
{
if (auto const PosableOne = Cast<IPosableOneInterface>(GetPawn()))
PosableOne->EndPoseA();
}
void AGPCPlayerController::EndPoseB()
{
if (auto const PosableOne = Cast<IPosableOneInterface>(GetPawn()))
PosableOne->EndPoseB();
}
//GPCPlayerController.cpp
함수를 정의하고 SetupInputComponet에서 Move,Look처럼 바인드 시켜준다. 액션축이니 BindAction 사용
InputComponent->BindAction("PoseA", EInputEvent::IE_Pressed, this, &ThisClass::BeginPoseA);
InputComponent->BindAction("PoseB", EInputEvent::IE_Pressed, this, &ThisClass::BeginPoseB);
InputComponent->BindAction("PoseA", EInputEvent::IE_Released, this, &ThisClass::EndPoseA);
InputComponent->BindAction("PoseB", EInputEvent::IE_Released, this, &ThisClass::EndPoseB);
'언리얼 C++ 정리' 카테고리의 다른 글
09/22 학습정리 (0) | 2023.09.25 |
---|---|
09/20 학습정리 ( Weapon Class추가) (1) | 2023.09.21 |
09/13 학습정리 (SetupAttachment, Look, PlayerController ) (0) | 2023.09.14 |
09/11 학습정리( Movement 구현 , Component 추가) (0) | 2023.09.12 |
09/07 학습 정리( Log, Print, Extern, Static, Namespace ) (0) | 2023.09.07 |