Menu
Coddy logo textTech

중첩 클래스와 내부 클래스

Coddy C++ 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 104개 중 38번째.

중첩 클래스는 다른 클래스 내부에 정의된 클래스입니다. 이 기법은 관련된 타입을 함께 그룹화하여 코드를 구성하는 데 도움이 되며, 구현 세부 정보를 숨겨 캡슐화를 강화할 수 있습니다.

class LinkedList {
public:
    class Node {    // 중첩 클래스
        int data;
        Node* next;
    public:
        Node(int d) : data(d), next(nullptr) {}
        friend class LinkedList;
    };
    
private:
    Node* head;
    
public:
    LinkedList() : head(nullptr) {}
};

중첩 클래스 NodeLinkedList와 긴밀하게 결합되어 있어 해당 맥락에서만 의미가 있습니다. 이를 중첩하면 이러한 관계를 나타내고, "Node"와 같은 일반적인 이름으로 전역 네임스페이스를 오염시키는 것을 방지할 수 있습니다.

Nested class는 지금까지 배운 것과 동일한 접근 규칙을 따릅니다. private 섹션에 선언된 Nested class는 바깥쪽 class 내부에서만 접근할 수 있습니다.

public으로 선언하면 외부 코드에서 범위 연산자를 사용하여 이를 사용할 수 있습니다:

LinkedList::Node node(42);    // Node가 public인 경우에만

방향과 관련해 한 가지 중요한 세부 사항이 있습니다. Nested class는 enclosing class의 멤버이며 다른 멤버와 동일한 접근 권한을 가지므로, friend 선언 없이도 enclosing class의 private 멤버에 액세스할 수 있습니다. 하지만 그 반대가 자동으로 성립하는 것은 아닙니다. enclosing class는 Nested class의 private 멤버에 액세스할 수 없습니다.

그렇기 때문에 위의 예제에서 Nodefriend class LinkedList;를 선언합니다. friend 선언은 이를 포함하는 LinkedListNode의 private 멤버에 접근할 수 있도록 허용하며, 이는 자동으로 허용되지 않는 유일한 방향입니다.

challenge icon

챌린지

쉬움

프로젝트 내에서 작업이 구성되는 간단한 작업 관리 시스템을 만들어 보겠습니다. 이는 중첩 클래스에 완벽한 시나리오입니다. TaskProject의 맥락 안에서만 의미가 있으므로, 코드를 체계적으로 유지하고 전역 namespace를 오염시키지 않도록 Project 내부에 중첩하겠습니다.

코드를 구성하기 위해 두 개의 파일을 만듭니다.

  • Project.h: 중첩된 Task 클래스를 포함하는 Project 클래스를 define합니다.

    중첩된 Task 클래스는 외부에서 접근할 수 있도록 Projectpublic 섹션에 선언해야 합니다. 작업 이름(string)과 완료 상태(bool)를 저장해야 합니다. 이름을 인수로 받고 기본적으로 작업을 incomplete 상태로 설정하는 constructor를 제공하세요. 작업을 완료 상태로 mark하는 complete(), 상태를 check하는 isComplete(), 이름을 가져오는 getName() 메서드를 포함하세요.

    Project 클래스 자체는 프로젝트 이름(string)과 Task 포인터의 컬렉션을 저장해야 합니다. 프로젝트 이름을 인수로 받는 constructor, 새 작업을 생성하여 프로젝트에 추가하는 addTask(const std::string& taskName) 메서드, 이름으로 작업을 find하여 완료하는 completeTask(const std::string& taskName) 메서드, 프로젝트 이름 뒤에 각 작업의 상태를 표시하는 displayStatus() 메서드를 제공하세요.

    TaskProject 내부에 중첩되어 있으므로 Project 클래스는 작업을 직접 다룰 수 있습니다. destructor에서 dynamically 할당된 작업을 정리하는 것을 잊지 마세요.

  • main.cpp: 입력에서 프로젝트 이름과 두 작업 이름을 읽어(총 세 줄) 모든 것을 하나로 결합합니다. 주어진 이름으로 Project를 생성하고, 두 작업을 모두 추가한 다음 초기 상태를 표시하세요. 첫 번째 작업을 완료하고 변경 사항을 보여 주도록 상태를 다시 표시하세요.

    displayStatus()의 출력 형식은 다음과 같아야 합니다.

    Project: <project_name>
      - <task_name>: [incomplete]
      - <task_name>: [complete]

    각 작업의 상태에 따라 [complete] 또는 [incomplete]를 사용하세요.

이 도전 과제는 중첩 클래스가 관련 타입을 구성하는 데 어떻게 도움이 되는지 보여 줍니다. Task 클래스는 Project와 긴밀하게 결합되어 있으며 독립적으로는 의미가 없습니다. 이를 중첩함으로써 코드 구조에서 이 관계를 명확하게 나타낼 수 있습니다.

직접 해보기

#include <iostream>
#include <string>
#include "Project.h"

using namespace std;

int main() {
    // 입력 읽기
    string projectName;
    string task1Name;
    string task2Name;
    
    getline(cin, projectName);
    getline(cin, task1Name);
    getline(cin, task2Name);
    
    // TODO: 주어진 이름으로 Project 생성
    
    // TODO: 프로젝트에 두 작업을 모두 추가
    
    // TODO: 초기 상태 표시
    
    // TODO: 첫 번째 작업 완료
    
    // TODO: 변경 사항을 보여주기 위해 상태를 다시 표시
    
    return 0;
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 C++ 컴파일러