변환 생성자

변환 생성자 (Converting constructor)

어떤 타입에서 다른 타입으로 값이 자연스럽게 "바뀌는" 걸 허용하려면 생성자를 하나 열어두면 돼요. explicit이 붙지 않고 단일 매개변수(until C++11)로 호출될 수 있는 생성자를 변환 생성자라고 불러요.

출처: cppreference

본문

explicit 지정자로 선언되지 않고, 단일 매개변수(until C++11)로 호출될 수 있는 생성자를 변환 생성자(converting constructor)라고 해요.

직접 초기화(direct initialization)에서만 고려되는 explicit 생성자(그리고 static_cast 같은 명시적 변환을 포함)와 달리, 변환 생성자는 사용자 정의 변환 시퀀스(user-defined conversion sequence)의 일부로 복사 초기화(copy initialization)에서도 고려돼요.

변환 생성자는 인자(있다면)의 타입에서 자기 클래스 타입으로의 암시적 변환을 지정한다고 말해요. 비-explicit 사용자 정의 변환 함수도 암시적 변환을 지정한다는 점을 참고하세요.

암시적으로 선언된(implicitly-declared) 그리고 사용자 정의된 비-explicit 복사 생성자와 이동 생성자는 변환 생성자예요.

예제 (Example)

struct A
{
    A() { }         // converting constructor (since C++11)  
    A(int) { }      // converting constructor
    A(int, int) { } // converting constructor (since C++11)
};

struct B
{
    explicit B() { }
    explicit B(int) { }
    explicit B(int, int) { }
};

int main()
{
    A a1 = 1;      // OK: copy-initialization selects A::A(int)
    A a2(2);       // OK: direct-initialization selects A::A(int)
    A a3{4, 5};    // OK: direct-list-initialization selects A::A(int, int)
    A a4 = {4, 5}; // OK: copy-list-initialization selects A::A(int, int)
    A a5 = (A)1;   // OK: explicit cast performs static_cast, direct-initialization

//  B b1 = 1;      // error: copy-initialization does not consider B::B(int)
    B b2(2);       // OK: direct-initialization selects B::B(int)
    B b3{4, 5};    // OK: direct-list-initialization selects B::B(int, int)
//  B b4 = {4, 5}; // error: copy-list-initialization selected an explicit constructor
                   //        B::B(int, int)
    B b5 = (B)1;   // OK: explicit cast performs static_cast, direct-initialization
    B b6;          // OK, default-initialization
    B b7{};        // OK, direct-list-initialization
//  B b8 = {};     // error: copy-list-initialization selected an explicit constructor
                   //        B::B()

    [](...){}(a1, a4, a4, a5, b5); // may suppress "unused variable" warnings
}

여기서 핵심은 = 1 같은 복사 초기화와 (2) 같은 직접 초기화의 차이예요. explicit이 붙은 B는 복사 초기화에서는 호출되지 않아서 B b1 = 1;이 컴파일 오류가 나죠. 직접 초기화(B b2(2);)는 문제없어요.

더 알아보기 (Learn more)

  • 복사 대입 — operator=를 통한 복사 대입 연산자.
  • 복사 생성자 — 같은 타입 객체로부터 초기화하는 생성자.
  • 복사 생략 — 복사·이동 생성이 생략될 수 있는 상황.
  • 기본 생성자 — 인자 없이 호출되는 생성자.
  • 소멸자 — 객체 수명이 끝날 때 호출되는 함수.
  • explicit — 암시적 변환을 금지하는 지정자.