소년코딩

생성자 위임 (Delegating constructors)

새 객체를 인스턴스화하면 C++ 컴파일러에 의해 생성자가 호출된다. 클래스에 여러 개의 생성자가 있는 경우 각 생성자의 기능이 중복되는 경우가 많다. 다음 예시를 보자:

class Test
{
public:
    Test()
    {
        // Code A
    }

    Test(int value)
    {
        // Code A
        // Code B
    }
};

위 코드에서 Test 클래스는 생성자 두 개를 가지고 있다.

  • 기본 생성자
  • 정수를 인수로 받는 생성자

두 생성자 모두 Code A 를 수행하므로 중복된 코드를 가지게 된다.

중복 코드를 갖는 것은 가능한 한 피해야 좋으므로 이 문제를 해결하기 위한 몇 가지 방법을 살펴보자.


확실하지만 잘못된 방법

class Test
{
public:
    Test()
    {
        // Code A
    }

    Test(int value)
    {
        Test(); // 위의 생성자(기본 생성자)를 호출한다.
        // Code B
    }
};

위 코드처럼 생성자 안에서 다른 생성자를 호출하면 잘 작동한다. 그러나 나중에 순서가 꼬이는 등의 이유로 오류가 일어난다면 디버거 하는데 오랜 시간을 할애하게 될 것이다.


생성자 위임 (Delegating constructors)

C++ 11에서는 생성자에서 다른 생성자를 호출하는 방법으로 생성자 위임(Delegating constructors)이라는 기능을 제공한다.

생성자에서 다른 생성자를 호출하려면 멤버 초기화 리스트에서 생성자를 호출하면 된다.

class Test
{
private:

public:
    Test()
    {
        // Code A
    }

    Test(int value) : Test() // Test() 기본 생성자를 호출한다.
    {
        // Code B
    }
};

이렇게 하면 Test 인스턴스가 생성될 때 기본 생성자(Test())가 호출된 후 정수를 인수로 받는 생성자(Test(int))가 호출되는 순으로 처리된다.

중복코드를 줄이기 위해 생성자 위임을 하는 또 다른 예시를 보자:

#include <string>
#include <iostream>

using namespace std;

class Employee
{
private:
    int m_ID;
    string m_Name;

public:
    Employee(int id, const string &name) : m_ID(id), m_Name(name)
    {
        cout << "Employee " << m_Name << " created.\n" << endl;
    }

    // 중복 코드를 최소화하기 위해 생성자 위임을 사용
    Employee(const string& name) : Employee(0, name)
    {

    }
};

위 클래스는 2개의 생성자를 가지고 있으며, 그중 1개는 다른 생성자를 위임한다. 이렇게 하면 중복 코드의 양이 최소화된다.

Note

같은 기능을 가진 여러 생성자가 있는 경우, 중복 코드를 최소화하도록 생성자를 위임하자!


함수 사용하기

관련해서, 생성자에서 멤버 함수를 호출할 수 있으므로 클래스의 멤버 변수를 기본값으로 초기화하기 위해 멤버 함수를 쓰고 싶은 상황이 있을 수 있다.

다음 예시를 보자:

class Test
{
public:
    Test()
    {
        Init();
    }

    Test(int value)
    {
        Init();

        // value를 가지고 뭔가하는 코드
    }

    void Init()
    {
        Test를 초기화하는 코드
    }
};

Init() 함수의 기능을 초기화(Initialize)라고 부르겠지만 이것은 진정한 초기화가 아니다.

생성자가 init() 함수를 호출할 시점에는 멤버 변수가 이미 존재하고 기본값(default value)으로 초기화되었을 것이다. Init() 함수는 멤버 변수의 값을 할당할 뿐이다. 이 방식으로는 const 또는 reference 변수와 같이 초기값이 필요한 멤버를 초기화할 수 없다.

주의사항

멤버 변수를 기본값으로 초기화하는 기능을 가진 init()과 같은 함수는 일반적으로 많이 쓰인다. 그러나 init() 함수는 언제든지 누구나 호출할 수 있으므로 init() 함수를 호출할 때 동적으로 할당된 메모리가 이미 할당되어 있거나 하는 상황이 있을 수 있다. 그러므로 이 상황을 적절하게 처리하도록 주의해서 프로그래밍하자.


cpp 번역: 이 포스트의 원문은 https://www.learncpp.com/cpp-tutorial/8-6-overlapping-and-delegating-constructors/ 입니다.

댓글 로드 중…

블로그 정보

소년코딩 - 소년코딩

소년코딩, 자바스크립트, C++, 물리, 게임 코딩 이야기

최근에 게시된 이야기