티스토리 뷰

반응형

🧠 C++에서 Nested Type이란?

― 클래스 안에 숨겨진 타입들을 제대로 이해하고 사용하는 법




✅ 1. 정의: Nested Type이란?

Nested Type(중첩 타입)이란 클래스 내부에 정의된 타입을 의미합니다. 즉, 클래스 안에 다른 타입(class, struct, enum, typedef, using 등)논리적으로 묶어 정의하는 것입니다.



✅ 2. 쓰임: Nested Type은 언제, 왜 사용될까?

상황 설명 예시
관련 타입을 한 곳에 묶고 싶을 때 내부 클래스, 설정 값 등을 내부에 포함 Tree::Node, Button::Style
외부에 타입을 감추고 싶을 때 내부 구현용 타입만 숨김 Impl, Helper
이름 충돌을 방지하고 싶을 때 전역에서 Node가 겹치는 상황 방지 Graph::Node, UI::Node

설명:
이처럼 Nested Type은 스코프를 명확하게 하고, 의미상 포함관계를 코드로 표현하며, 타입 설계의 안정성을 크게 높여줍니다.


반응형

 


✅ 3. 필요성: 왜 굳이 클래스 안에 타입을 넣어야 하나?

🔻 문제 상황

#include <iostream>
using namespace std;

struct Node {
    int data;
};
struct Graph {
    Node root; // 어느 Node? 의미 모호
};

전역에 선언된 타입은 어떤 클래스에 속하는지 알 수 없습니다.
이로 인해 의미도 불분명하고, 타입 이름이 겹칠 가능성도 높아집니다.


✅ 4. 해결책: Nested Type으로 포함관계와 이름 공간 분리

class Graph {
public:
    struct Node {
        int data;
    };

    Node root;
};

이렇게 하면 Graph::Node처럼 명확한 이름 공간(namespace) 안에서 의미상 종속된 타입을 정의할 수 있습니다.


✅ 5. 타입별 예제

✅ 예제 1: Nested Class

▶ 코드 전 설명

Container 클래스 안에 Item 클래스를 중첩합니다. Item은 오직 Container 내부에서만 의미 있는 클래스입니다.
#include <iostream>
using namespace std;

class Container {
public:
    class Item {
    public:
        Item(int v) : value(v) {}
        int getValue() const { return value; }
    private:
        int value;
    };

    Item createItem(int x) {
        return Item(x);
    }
};

int main() {
    Container c;
    Container::Item item = c.createItem(10);
    cout << "Item 값: " << item.getValue() << endl;
    return 0;
}

▶ 출력 결과

Item 값: 10

▶ 코드 후 설명

  • Item은 Container 안에만 존재합니다.
  • 스코프 제한을 통해 이름 충돌을 방지합니다.



반응형

 


✅ 예제 2: Nested Struct

▶ 코드 전 설명

Database 클래스 안에 Record 구조체를 중첩하여 내부 전용 데이터 단위를 표현합니다.
#include <iostream>
#include <vector>
using namespace std;

class Database {
public:
    struct Record {
        int id;
        string name;

        void print() const {
            cout << "ID: " << id << ", 이름: " << name << endl;
        }
    };

    void add(int id, const string& name) {
        records.push_back({id, name});
    }

    void showAll() const {
        for (const Record& r : records) {
            r.print();
        }
    }

private:
    vector<Record> records;
};

int main() {
    Database db;
    db.add(1, "홍길동");
    db.add(2, "김철수");
    db.showAll();
    return 0;
}

▶ 출력 결과

ID: 1, 이름: 홍길동
ID: 2, 이름: 김철수

▶ 코드 후 설명

  • Record는 Database 내부에 소속된 자료 단위입니다.
  • 외부로부터 의미상 구분된 구조를 제공합니다.



✅ 예제 3: Nested Enum

▶ 코드 전 설명

Game 클래스에 Difficulty 열거형(enum)을 중첩합니다. 난이도는 Game에 종속된 개념입니다.
#include <iostream>
using namespace std;

class Game {
public:
    enum class Difficulty { Easy, Medium, Hard };

    void setDifficulty(Difficulty d) {
        difficulty = d;
    }

    void printDifficulty() const {
        switch (difficulty) {
            case Difficulty::Easy: cout << "난이도: 쉬움" << endl; break;
            case Difficulty::Medium: cout << "난이도: 보통" << endl; break;
            case Difficulty::Hard: cout << "난이도: 어려움" << endl; break;
        }
    }

private:
    Difficulty difficulty;
};

int main() {
    Game g;
    g.setDifficulty(Game::Difficulty::Medium);
    g.printDifficulty();
    return 0;
}

▶ 출력 결과

난이도: 보통

▶ 코드 후 설명

  • Difficulty는 Game에서만 의미가 있습니다.
  • enum class + 중첩 구조로 이름 충돌을 피합니다.



✅ 예제 4: Nested typedef

▶ 코드 전 설명

User 클래스 안에서 int에 ID라는 별칭을 typedef로 부여합니다. 독립된 식별자처럼 보이도록 합니다.
#include <iostream>
using namespace std;

class User {
public:
    typedef int ID;

    User(ID uid) : id(uid) {}

    void printID() const {
        cout << "사용자 ID: " << id << endl;
    }

private:
    ID id;
};

int main() {
    User::ID id = 101;
    User u(id);
    u.printID();
    return 0;
}

▶ 출력 결과

사용자 ID: 101

▶ 코드 후 설명

  • ID는 실제로는 int이지만, 의미 있는 이름으로 사용됩니다.
  • 스코프 충돌 없이 동일한 이름을 여러 클래스에서 사용할 수 있습니다.



✅ 예제 5: Nested using

▶ 코드 전 설명

현대 C++ 문법인 using을 사용해 std::string을 의미 있는 이름으로 표현합니다.
#include <iostream>
#include <string>
using namespace std;

class Profile {
public:
    using Name = string;

    Profile(Name n) : name(n) {}

    void greet() const {
        cout << "안녕하세요, " << name << "님!" << endl;
    }

private:
    Name name;
};

int main() {
    Profile::Name username = "김코딩";
    Profile p(username);
    p.greet();
    return 0;
}

▶ 출력 결과

안녕하세요, 김코딩님!

▶ 코드 후 설명

  • using으로 가독성 있는 타입 이름을 정의합니다.
  • 타입 이름을 통해 코드의 의미를 명확하게 합니다.



✅ 6. 최종 요약 정리표

타입 종류 키워드 접근 방식 목적
클래스 class Outer::Inner 내부 전용 객체 설계
구조체 struct Outer::StructName 내부 데이터 집합 표현
열거형 enum Outer::EnumName::Value 내부 상태 정의
별칭 (전통) typedef Outer::AliasName 의미 있는 타입 이름 부여
별칭 (현대) using Outer::AliasName 템플릿, 긴 타입에 간단한 이름 부여



✅ 결론

  • Nested Type은 클래스 내부에 정의된 타입입니다.
  • 스코프 관리, 이름 충돌 방지, 구조적 코드 설계에 필수적입니다.
  • Tree의 Node, UI의 Style 등 다양한 실전 사례에서도 자주 사용됩니다.



반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/06   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함