Information Technology/C++

[C++] 변환 생성자와 explicit

이웃어 2019. 11. 19. 00:26

이 글은 개인의 학습을 목적으로 정리한 글입니다. 이점 참고하고 읽어주세요 ;)


이번에는 클래스를 다룰 때 사용할 수 있는 변환 생성자Converting constructor, explicit, delete를 다뤄보려고 합니다.

class Add
{
private:
	m_int;
public:
    Add(int value = 0) : m_int(value) {}
    
    friend print(Add add);
};

void print(Add add)
{
	cout << add.m_int << endl;
}

여기 Add 클래스가 있습니다. Add 클래스는 생성자로 int형 변수를 입력받아 그 값을 m_int에 저장합니다.

그리고 Add 클래스 자료형의 인스턴스를 매개변수로 받는 print 함수가 있습니다. print 함수는 매개변수로 받은 add의 m_int를 출력합니다. Add 클래스에서 friend 선언을 했기 때문에 외부에서도 m_int를 사용할 수 있습니다.

int main()
{
    Add add(7);
    
    print(add); // 7
    print(7);	// 7
    
    return 0;
}

이제 main함수에서 Add 클래스 자료형 add를 생성하고 print 함수에 add를 인자로 주었습니다. 7이 출력됩니다.

그런데 print함수에 add가 아닌 그냥 7을 인자로 주어도 똑같이 7이 생성됩니다. 어떻게 된 걸까요?

이는 컴파일러가 자체적으로 변환 생성자converting constructor를 호출하기 때문이라고 합니다.

컴파일러에서 print함수를 사용하려고 하는데, 어라? 인자로 받은 값이 Add 클래스 자료형의 인스턴스가 아니라 그냥 정수 7인 상황인겁니다. 컴파일러는 여기서 에러를 내지 않고 침착하게 코드를 훑어본 후 인자로 받은 7을 print 함수에서 사용할 수 있게 Add 클래스 인스턴스를 7로 생성해서 그 인스턴스의 m_value값을 print 함수에 주는 방식입니다.

이렇게 컴파일러가 스스로 값을 변환하는 것을 변환 생성자convert constructor라고 합니다.


class Add
{
private:
	m_int;
public:
    explicit Add(int value = 0) : m_int(value) {}
    
    friend print(Add add);
};

void print(Add add)
{
	cout << add.m_int << endl;
}

이번에는 같은 Add 클래스에서 생성자 앞에 explicit 선언을 해줬습니다. explicit을 사전에 찾아보면 분명한, 명쾌한 등등의 단어가 나옵니다. '생성자 선언을 명쾌하게 해라!' 정도로 생각하면 될 것 같아요. ㅋㅋ이게 정확히 무슨 의미냐면

int main()
{
    Add add(7);
    
    print(add); // 7
    print(7);	// error!
    
    return 0;
}

main 함수를 위에서 그대로 가져와서 실행을 하게되면, 아까는 변환 생성자 덕분에 이상 없이 출력되었던 print(7)이라는 코드가 에러를 발생시킵니다. 바로 Add 클래스를 생성할 때 생성자에 explicit 선언을 했기 때문입니다.

즉, explicit 선언을 통해 변환 생성자convert constructor가 호출되는 것을 막는다고 생각하면 될 것 같습니다!