C++ 공부

[C++ Study] friend, 상속의 경계, 그리고 static의 메모리 전략

Client Side 2026. 4. 10. 10:57

1. friend 키워드: 캡슐화의 전략적 해제

friend는 클래스의 private 멤버에 접근할 수 있는 권한을 특정 외부 대상에게 부여하는 강력한 도구입니다.

📋 교과서적 정의

  • 개념: 클래스 내부에 friend로 선언된 외부 함수나 클래스는 해당 클래스의 모든 접근 제한자를 무시하고 멤버에 접근할 수 있습니다.
  • 특징:
    • 단방향성: A가 B를 친구로 선언해도, A가 B의 비공개 멤버를 볼 수는 없습니다.
    • 전이되지 않음: 친구의 친구는 내 친구가 아닙니다.
    • 상속되지 않음: 부모의 친구가 자식 클래스까지 자동으로 친구가 되지는 않습니다.

🛠️ 특정 함수에 대한 friend 선언

클래스 전체가 아니라 특정 멤버 함수에만 권한을 열어주어 **'최소 권한의 원칙'**을 지킬 수 있습니다.

// A.h
class A {
public:
    void SpecificFunction(class B& b); // 선언만 존재
};

// B.h
class B {
private:
    int SecretData;

    // A 클래스의 전체가 아니라 'SpecificFunction'에게만 열쇠를 넘겨줌
    friend void A::SpecificFunction(B& b); 
};

핵심 가이드: friend 선언은 내가 남의 집에 들어가는 권한을 얻는 것이 아니라, "내 집의 열쇠를 너에게 줄게"라고 선언하는 주체적인 권한 부여입니다.


2. 구조체(struct)와 클래스(class)의 상속과 혼용

C++에서 두 구조는 문법적으로 거의 동일하며 상속을 주고받는 데 제약이 없습니다.

📋 상속 시 주의점: 접근 제어자 기본값

  • 구조체(struct): 상속 및 멤버의 기본 접근 제어자가 public입니다.
  • 클래스(class): 상속 및 멤버의 기본 접근 제어자가 private입니다.

💡 실무적 판단

  • 의도의 명확성: 문법적으로는 혼용이 가능하나, 데이터 중심(POD)은 struct, 기능과 로직 중심은 class로 구분하여 설계 의도를 명확히 하는 것이 유지보수에 유리합니다.
  • 메모리 레이아웃: 구조체에 가상 함수가 포함되거나 클래스를 상속받으면 vptr(가상 함수 테이블 포인터)이 추가되어 메모리 크기가 커질 수 있음을 유의해야 합니다.

3. static: 생명 주기와 가시성의 제어

static은 변수가 저장되는 메모리 위치와 데이터를 볼 수 있는 범위(Scope)를 결정합니다.

📋 위치에 따른 기능 차이

  1. 함수 내부 (정적 지역 변수): 함수가 끝나도 소멸하지 않고 값이 유지됩니다. 첫 호출 시 단 한 번 초기화됩니다.
  2. 클래스 내부 (정적 멤버 변수): 인스턴스가 아닌 클래스 자체에 귀속되며, 모든 객체가 데이터를 공유합니다.
  3. 파일 범위 (정적 전역 변수): 해당 파일(.cpp) 내부에서만 접근 가능하도록 제한합니다(Internal Linkage).

📁 메모리 영역: .data vs .bss

시스템은 실행 파일의 크기를 최적화하기 위해 데이터 영역을 나눕니다.

  • .data 영역: 초기값이 있는 전역/정적 변수가 저장됩니다. (파일 용량 차지)
  • .bss 영역: 초기값이 없거나 0으로 초기화된 변수가 저장됩니다. 실제 값 대신 "공간 필요" 정보만 기록하여 실행 파일 크기를 줄입니다.

4. 스레드(Thread): 효율적인 병렬 처리

스레드는 프로세스 내에서 독립적으로 작업을 수행하는 최소 단위입니다.

📋 멀티스레딩의 명과 암

  • 장점: 병렬 처리를 통해 무거운 연산(물리, 로딩, AI)을 메인 루프와 분리하여 게임의 응답성을 높입니다.
  • 위험성:
    • 데이터 경합(Race Condition): 여러 일꾼이 동시에 하나의 데이터를 수정할 때 발생하는 논리 오류.
    • 데드락(Deadlock): 서로가 가진 자원을 기다리며 무한히 멈추는 상태.

🛠️ 설계 전략

  • 동기화 객체: 뮤텍스(Mutex), 크리티컬 섹션 등을 통해 안전한 접근을 보장합니다.
  • 대안: 과도한 동기화는 성능 저하를 일으키므로, 태스크 그래프(Task Graph) 시스템을 활용해 데이터를 분리하거나 원자적(Atomic) 연산을 사용하는 것이 효율적입니다.