주제

  • 이 강의의 주제는 C++ 객체지향 프로그래밍의 핵심 요소들을 통합적으로 이해하고 응용하는 것입니다.
  • 특히 추상 클래스와 인터페이스, 다형성 구현, 캡슐화, 상속, 연산자 오버로딩, static과 싱글톤 패턴을 포함한 OOP 구조 전반을 정리하며, 실전 예제를 통해 구현 원리를 설명합니다.
  • 객체지향 프로그래밍의 기초부터 실제 게임 개발 등에서 자주 활용되는 싱글톤 구조까지 포괄적으로 마무리하는 파트입니다.

개념

1. 객체지향 프로그래밍(OOP)의 4대 핵심

개념설명
캡슐화(Encapsulation)데이터와 기능을 하나의 클래스에 묶고, 외부 접근을 제한하여 안정성을 확보
상속(Inheritance)기존 클래스의 속성과 기능을 새로운 클래스가 물려받아 재사용 가능
다형성(Polymorphism)동일한 인터페이스로 다양한 객체를 다룰 수 있게 하여 유연한 코드 구조 제공
추상화(Abstraction)객체의 내부 구현을 숨기고, 중요한 기능만을 외부에 노출함

용어정리

용어설명
추상 클래스순수 가상 함수를 포함하며, 인스턴스화될 수 없는 클래스
순수 가상 함수virtual void 함수명() = 0; 형태로 정의되어, 반드시 파생 클래스에서 구현해야 함
인터페이스순수 가상 함수만으로 구성된 클래스. 기능의 틀(스펙)을 제공
다형성같은 인터페이스로 다른 타입의 객체를 제어하며, 실제 객체의 타입에 따라 동작이 달라짐
오버라이딩상속받은 함수를 자식 클래스에서 재정의하여 다른 동작을 수행하도록 하는 것
연산자 오버로딩연산자(= 등)의 동작을 클래스에 맞게 새롭게 정의하는 것
static클래스 수준에서 공유되는 변수 또는 함수. 인스턴스를 만들지 않아도 접근 가능
싱글톤 패턴클래스의 인스턴스를 하나로 제한하여 전역에서 공유하는 디자인 패턴

코드 분석


📌 1. 추상 클래스 정의

class Object
{
public:
    virtual void Shout() = 0; // 순수 가상 함수
};
  • Object 클래스는 순수 가상 함수 Shout()를 포함하므로 추상 클래스입니다.
  • 추상 클래스는 인스턴스를 생성할 수 없고, 반드시 상속받은 자식 클래스에서 해당 함수(Shout)를 구현해야 합니다.
  • 이 구조를 통해 다형성을 구현할 수 있습니다.

📌 2. 인터페이스 구현

class IFly
{
    virtual void Fly() = 0;
    virtual void Land() = 0;
public:
};
  • IFly인터페이스 클래스입니다. 모든 멤버 함수가 순수 가상 함수로 선언되어 있습니다.
  • 인터페이스는 클래스가 따라야 하는 약속(스펙) 을 정의합니다.
  • 이를 상속받은 클래스는 반드시 Fly()Land()를 구현해야 합니다.

📌 3. 다중 상속을 통한 다형성 구현

class Player : public Object, public IFly
{
public:
    Player() {}
    ~Player() {}

    virtual void Shout() override
    {
        // Object 추상 클래스의 Shout 함수 구현
    }

    virtual void Fly() override
    {
        // IFly 인터페이스의 Fly 함수 구현
    }

    virtual void Land() override
    {
        // IFly 인터페이스의 Land 함수 구현
    }

    void Move() {} // 일반 멤버 함수
    void SetHP(int hp) { this->hp = hp; } // 캡슐화된 멤버 변수에 대한 setter

private:
    int hp; // 외부에서 접근할 수 없도록 캡슐화된 멤버
};
  • Player 클래스는 Object, IFly 두 클래스를 다중 상속합니다.
  • Shout, Fly, Land 함수는 오버라이딩(override) 되어 다형성을 실현합니다.
  • hp 변수는 private으로 선언되어 외부에서 직접 접근할 수 없으며, SetHP()를 통해 간접 설정하게 하여 캡슐화가 적용되어 있습니다.

📌 4. 연산자 오버로딩

Player& operator=(const Player& other)
{
    if (this != &other)
    {
        this->hp = other.hp;
    }
    return *this; // 자기 자신 반환 → 연쇄 대입 가능
}
  • 대입 연산자(=)를 오버로딩하여 Player 객체 간 복사를 정의합니다.
  • this != &other는 자기 자신에 대한 대입을 방지합니다.
  • *this를 반환함으로써 a = b = c 같은 연쇄 대입이 가능해집니다.

📌 5. Static과 싱글톤

🔹 정적 멤버

class Marine
{
public:
    static int attackPower; // 정적 멤버 변수
    static void SetAttackPower(int power) { attackPower = power; } // 정적 멤버 함수
};
int Marine::attackPower = 0;
  • attackPower모든 객체가 공유하는 정적 멤버 변수입니다.
  • Marine::SetAttackPower()는 객체 없이 호출 가능한 정적 함수로, 클래스 자체에서 동작합니다.

🔹 싱글톤 패턴

class UserManager
{
public:
    static UserManager* GetInstance()
    {
        static UserManager instance;
        return &instance;
    }

    void AddUser() { userCount++; }
    int GetUserCount() { return userCount; }

private:
    int userCount = 0;
};
  • GetInstance() 함수는 내부에 static UserManager instance를 생성하여, 단 한 번만 객체가 생성되도록 보장합니다.
  • 전역에서 동일한 UserManager 객체를 공유하여 사용하게 됩니다.

📌 6. 다형성 테스트 실행 예

void FlyTest(IFly* fly)
{
    fly->Fly();
    fly->Land();
}

int main()
{
    Player p1;
    p1.SetHP(100);   // 캡슐화된 hp 설정
    p1.Fly();        // 직접 호출
    p1.Land();       // 직접 호출

    FlyTest(&p1);    // 다형성: IFly 포인터로 Player 다룸
    return 0;
}
  • FlyTest(IFly* fly) 함수는 인터페이스 포인터를 인자로 받기 때문에, 실제로 어떤 객체든 IFly를 구현했다면 호출 가능합니다.
  • Player 객체는 IFly를 상속받았기 때문에 전달이 가능하며, 내부 구현에 따라 Fly()Land()가 호출됩니다.

핵심

  • 객체지향의 네 가지 핵심(캡슐화, 상속, 다형성, 추상화)을 직접 구현해보는 실습 중심의 마무리 강의입니다.
  • 추상 클래스와 인터페이스를 통해 다형성을 구현하며, 클래스 구조의 유연성을 확보합니다.
  • 캡슐화를 통해 데이터 보호인터페이스 제공 방식을 학습합니다.
  • 연산자 오버로딩을 통해 객체 간 대입 연산을 정의하고, 연쇄 대입도 가능하게 합니다.
  • static 키워드를 통해 공통된 값의 공유 및 클래스 함수 구현 방식을 익히고,
  • 싱글톤 패턴을 통해 단일 객체 생성 및 전역 관리 기법을 실제로 구현합니다.
  • 이 모든 요소들은 추상적 이론이 아닌, 실제 예제와 실행 흐름을 통해 구성되어 게임 개발, 유틸리티 매니저 등 실전 설계에 필요한 기반이 됩니다.

profile
李家네_공부방

0개의 댓글