Menu
Coddy logo textTech

생성자 초기화 리스트

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

이전 레슨에서 Player(std::string n, int h) : name(n), health(h) {}와 같은 콜론 구문을 보았습니다. 이것은 멤버 초기화 리스트라고 불리며, C++에서 멤버를 초기화하는 권장되는 방법입니다.

초기화 리스트는 생성자의 매개변수 목록 뒤에 콜론(:)으로 시작하여 나타납니다. 각 멤버는 쉼표로 구분되어 해당 값으로 직접 초기화됩니다:

class Rectangle {
    int width;
    int height;
    const int id;
    int& reference;
public:
    Rectangle(int w, int h, int i, int& r) 
        : width(w), height(h), id(i), reference(r) {
        // 생성자 본문 (비어 있을 수 있음)
    }
};

왜 생성자 본문에서의 대입 대신 초기화 리스트를 사용해야 할까요? 대입을 사용하면 멤버들이 먼저 기본 생성자로 생성된 후, 새로운 값이 대입됩니다. 초기화 리스트를 사용하면 멤버들이 올바른 값으로 직접 생성되므로, 더 효율적이며 때로는 필수적이기도 합니다.

특정 멤버들은 반드시 리스트를 사용하여 초기화되어야 합니다:

  • const 멤버 - 생성 후에는 할당할 수 없습니다.
  • 참조 멤버 - 초기화 시 반드시 바인딩되어야 합니다
  • 기본 생성자가 없는 멤버
class Player {
    const int maxHealth;    // 반드시 초기화 리스트를 사용해야 함
    std::string name;
public:
    // 이 방식은 작동합니다
    Player(int max, std::string n) : maxHealth(max), name(n) {}
    
    // 이 방식은 컴파일되지 않습니다:
    // Player(int max) { maxHealth = max; }  // 오류!
};

멤버는 초기화 리스트에 적힌 순서가 아니라 클래스에 선언된 순서대로 초기화됩니다. 혼동을 피하기 위해 항상 초기화 리스트를 선언 순서대로 작성하세요.

challenge icon

챌린지

쉬움

멤버 초기화 리스트(member initializer list)가 언제, 왜 필수적인지 보여주는 게임 엔진용 설정 시스템을 구축해 보겠습니다. 초기화 리스트 구문을 사용하여 반드시 초기화해야 하는 멤버들을 가진 GameConfig 클래스를 만들 것입니다.

코드를 정리하기 위해 두 개의 파일을 생성합니다:

  • GameConfig.h: 게임 설정을 저장하는 GameConfig 클래스를 정의합니다. 클래스에는 다음이 포함되어야 합니다:
    • const std::string gameName — 생성 후 변경할 수 없는 게임 제목
    • const int maxPlayers — 생성 시 고정되는 최대 플레이어 수
    • int& difficultyRef — 외부 난이도 설정에 대한 참조
    • int screenWidthint screenHeight — 디스플레이 설정을 위한 일반 멤버
    • 필요한 모든 매개변수를 받아 모든 멤버를 초기화 리스트를 사용하여 초기화하는 생성자. 초기화 리스트는 클래스에 멤버가 선언된 순서를 따라야 합니다.
    • 다음 형식으로 설정을 출력하는 display() 메서드:
      Game: <gameName>
      Max Players: <maxPlayers>
      Difficulty: <difficultyRef value>
      Resolution: <screenWidth>x<screenHeight>
  • main.cpp: 입력에서 설정 값을 읽고 GameConfig 객체를 생성합니다. 다음 작업이 필요합니다:
    • 입력에서 게임 이름(string), 최대 플레이어 수(int), 난이도(int), 너비(int), 높이(int)를 읽습니다. 각 값은 별도의 줄에 있습니다.
    • 설정 객체가 참조할 난이도용 로컬 int 변수를 생성합니다.
    • 초기화 리스트 생성자를 사용하여 GameConfig 객체를 생성합니다.
    • display()를 호출하여 초기 설정을 보여줍니다.
    • 난이도 변수를 직접 수정합니다 (2를 곱함).
    • "After difficulty change:"를 출력합니다.
    • display()를 다시 호출하여 참조 멤버가 업데이트된 값을 반영하는지 확인합니다.

이 챌린지는 초기화 리스트가 왜 중요한지 강조합니다. const 멤버와 참조 멤버는 생성자 본문에서 할당될 수 없으며, 반드시 초기화 리스트에서 초기화되어야 합니다. 또한 참조 멤버는 원본 변수의 변경 사항이 설정 객체를 통해 어떻게 반영되는지 보여줍니다.

main.cpp에 #include "GameConfig.h"를 사용하여 헤더 파일을 포함하세요.

치트 시트

멤버 초기화 리스트(member initializer list)는 C++에서 클래스 멤버를 초기화하는 권장되는 방법입니다. 이는 생성자의 매개변수 목록 뒤에 콜론으로 시작하며, 각 멤버가 직접 초기화됩니다:

class Rectangle {
    int width;
    int height;
public:
    Rectangle(int w, int h) : width(w), height(h) {
        // 생성자 본문
    }
};

왜 초기화 리스트를 사용해야 할까요? 멤버가 기본 생성된 후 대입되는 대신 올바른 값으로 직접 생성되므로 더 효율적입니다.

특정 멤버의 경우 필수 사항입니다:

  • const 멤버 - 생성 후에는 값을 대입할 수 없습니다
  • 참조(Reference) 멤버 - 초기화 시 반드시 바인딩되어야 합니다
  • 기본 생성자가 없는 멤버
class Player {
    const int maxHealth;
    int& reference;
public:
    // 올바름 - 초기화 리스트 사용
    Player(int max, int& r) : maxHealth(max), reference(r) {}
    
    // 오류 - 본문에서 const 또는 참조 멤버에 대입할 수 없음
    // Player(int max) { maxHealth = max; }
};

중요: 멤버는 초기화 리스트에 나열된 순서가 아니라 클래스에 선언된 순서대로 초기화됩니다. 항상 초기화 리스트를 선언 순서대로 작성하세요.

직접 해보기

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

using namespace std;

int main() {
    // 입력값 읽기
    string gameName;
    getline(cin, gameName);
    
    int maxPlayers;
    cin >> maxPlayers;
    
    int difficulty;
    cin >> difficulty;
    
    int width;
    cin >> width;
    
    int height;
    cin >> height;
    
    // TODO: 초기화 리스트 생성자를 사용하여 GameConfig 객체 생성
    // 생성자는 gameName, maxPlayers, difficulty (참조로 전달), width, height를 전달받아야 함
    
    // TODO: display()를 호출하여 초기 설정 표시
    
    // TODO: difficulty 변수를 직접 수정 (2를 곱함)
    
    // TODO: "After difficulty change:" 출력
    
    // TODO: display()를 다시 호출하여 업데이트된 설정 표시
    
    return 0;
}
quiz icon실력 점검

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

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