[UE5] Get,Set함수

vector·2025년 5월 7일

C++ 클래스에서 데이터 멤버 (특히 UPROPERTY로 선언된 멤버)에 대한 캡슐화를 구현하는 대표적인 방식

Unreal의 객체 지향 설계 원칙에 따라, 외부에서 멤버 변수에 직접 접근하지 않고, Getter와 Setter 함수를 통해 간접적으로써 유효성 검사, 부가 처리, Blueprint와의 연동 등을 손쉽게 수행할 수 있다.

1. Blueprint 연동 가능한 Getter/Setter

UFUNCTION(BlueprintCallable, Category = "Stats")
float GetHealth() const;

UFUNCTION(BlueprintCallable, Category = "Stats")
void SetHealth(float NewHealth);

2. UPROPERTY와 함께 인라인 Get/Set 접근 제어

  • C++20 표줌에서처럼 속성(Property) 접근을 자동화하는 기능은 Unreal에서는 없지만, meta태그와 함수 매크로를 함께 사용하여 비슷한 효과를 낼 수 있다.
  • Health를 에디터에서 편집 가능하게 하면서, Blueprint에서의 접근은 지정된 함수로 제한되게 한다.
UPROPERTY(EditAnywhere, BlueprintGetter=GetHealth, BlueprintSetter=SetHealth, Category = "Stats")
float Health;


UFUNCTION(BlueprintGetter)
float GetHealth() const { return Health; }

UFUNCTION(BlueprintSetter)
void SetHealth(float NewHealth) { Health = NewHealth; }

3. Property 접근 예제 (C++ 사용시)

AMyActor* Actor = GetWorld()->SpawnActor<AMyActor>();
Actor->SetHealth(75.0f);

float CurrentHealth = Actor->GetHealth();
UE_LOG(LogTemp, Log, TEXT("Health is : %f"), CurrentHealth);

메타데이서 사용 방식과 기존 방식 차이점

1. BlueprintGetter / BlueprintSetter 메타데이터 사용 방식

UPROPERTY(EditAnywhere, BlueprintGetter=GetHealth, BlueprintSetter=SetHealth, Category = "Stats")
float Health;

UFUNCTION(BlueprintGetter)
float GetHealth() const { return Health; }

UFUNCTION(BlueprintSetter)
void SetHealth(float NewHealth) { Health = NewHealth; }
  • 장점
    • 직접 UPROPERTY를 노출하면서도 접근을 Getter/Setter로 통제할 수 있다
    • 변수는 직접 에디터에서 보이지만 Blueprint에서는 함수만을 통해 접근 가능하다
    • UI 노출을 제어하면서도 캡슐화 유지가 가능하다
  • 단점
    • 코드 구조가 약간 복잡해진다
    • 함수 이름과 변수 이름이 일치하지 않으면 혼란스러울 수 있다
    • 모든 Getter/Setter가 Blueprint에서 꼭 필요하지 않을 때에도 함수가 생긴다
  • 사용 적합한 상황들
    • Blueprint 사용자가 해당 값을 읽고 쓸 수 있어야 하지만, 내부적으로는 조건 검사 또는 후처리가 필요할 경우
    • 에디터에서 바로 변수 수정이 필요하고, 값 변경 시 부가 로직이 필요한 경우

2. 기존 방식

private:
    UPROPERTY(EditAnywhere)
    FString Name;

public:
    UFUNCTION(BlueprintCallable)
    const FString& GetName() const;

    UFUNCTION(BlueprintCallable)
    void SetName(const FString& NewName);
  • 장점
    • 완전한 캡슐화(외부에서는 항상 Get/Set 함수를 통해 접근해야 하며, 멤버 변수는 보호된다.)
    • 변수와 함수가 분리되므로 구조적으로 명확하다
    • 리플렉션 시스템과는 연결되지만, 에디터에 직접 노출되지 않는다.(의도적으로 숨기고 싶을 때 유용)
  • 단점
    • 에디터에서 변수값을 직접 설정할 수 없다.(수동으로 초기화하거나 디폴트값 설정 필요)
    • 간단한 데이터(예: 이름, 수치형 변수)조차 함수로만 접근해야 하므로 코드가 장황해질 수 있다
  • 사용 적합한 상황들
    • 변수 자체를 외부에 절대 노출시키지 않아야 하는 경우 (보안, 무결성 중요)
    • 런타임에서만 값 접근이 필요한 경우 (에디터에서는 설정 불필요)
    • 함수 내부에서 검사/로직이 복잡한 경우

const 위치

1. 함수 뒤에 붙는 const

float GetHealth() const;
  • 해당 함수가 객체의 멤버 변수를 변경하지 않음을 보장한다.
  • const 객치를 통해 호출할 수 있는 유일한 함수 유형
  • 주로 Getter 함수에 붙음

예시

float AMyActor::GetHealth() const
{
	return Health; // 멤버 변수 읽기만 할 경우 가능
}

void AMyActor::SetHealth(float NewHealth) const
{
	Health = NewHealth; // const 함수는 멤버 수정 불가능
}

2. 매개 변수에 붙는 const

void SetName(const FString& NewName);
  • 매개변수 NewName이 함수 내부에서 수정되지 않음을 나타낸다
  • 참조(reference)나 포인터(pointer)를 통해 전달되는 복잡한 자료형(FString, FVector, FTransform등)의 복사 비용을 줄이고 의도를 명확하게 한다.

예시

void AMyActor::SetName(const FString& NewName)
{
	Name = NewName; // 복사만 하고 수정은 불가능
}

3. 반환 타입에 붙는 const

const FString& GetName() const;
  • 반환되는 값을 함수 외부에서 수정하지 못하게 하기
  • 참조 반환(reference return)일 때 유용하다.

예시

const FString& AMaActor::GetName() const
{
	return Name;
}

// 외부 코드
FString Name = Actor->GetName(); // 가능
Actor->GetName() = TEXT("New"); // const 참조이므로 수정 불가능

정리

  • 함수 뒤에 const : 함수가 멤버를 변경하지 않음을 명시적으로 보장 --> 최적화, 안정성 향상
  • 매개 변수에 const : 불필요한 복사 방지, 값 보호 --> 특히 FString, FVector, FTransform등에 유리
  • 반환 타입에 const : 외부 코드가 반환값을 수정하지 못하게 막음 --> 참조 반환 시 사용
profile
게임 클라이언트 프로그래머 준비중 (공부 및 기록용)

0개의 댓글