2015. 2. 2.

[C++]생성자(constructor)

 C++이 C와 다른 점 중에 하나는 클래스(class)를 지원한다는 사실이다. 클래스를 이용해서 프로그래머는 객체지향적인 프로그래밍(OOP)을 할 수 있다. 이번에는 클래스를 사용함에 있어서 가장 먼저 접하게 되는 생성자(constructor)에 대해서 알아보고자 한다. 생성자에 대한 이해는 나중에 다루게 될 상속 개념, 깊은 복사(deep copy)와 얕은 복사(shallow copy), 복사 생성자 등을 이해하는데 꼭 필요하므로 반드시 이해하고 넘어가야 한다.


 생성자(constructor)
 매우 단순한 클래스이다. 이 클래스에는 생성자가 보이지 않는다. 클래스 생성자를 설명하겠다고 했지만, 생성자가 없는 코드를 보여주고 있다. 말 그대로 생성자는 클래스를 만드는 함수인데 생성자가 없이 클래스를 만들 수 있겠는가? 결론부터 이야기하자면 가능하다.

 먼저 위에 Simple 클래스의 객체를 생성해보자.
 위의 코드에서처럼 두 가지 방법으로 객체를 생성할 수 있다. 일반변수를 선언하듯이 만들수도 있고, new을 이용해서 동적 할당하여 생성할 수도 있다. 앞에서도 말했듯이 의문점은 Simple 클래스는 생성자가 선언되어 있지 않다. 하지만 분명한 사실은 객체가 생성되었다는 점이다. 우리가 모르는 뭔가가 있다는 소리이다. 이 뭔가가 바로 default 생성자이다.


디폴트 생성자(default constructor)

 생성자가 따로 선언되지 않은 클래스를 통해 객체를 생성하려고 하면, 디폴트 생성자가 자동으로 호출되어 객체를 만든다. 그래서 앞에서처럼 2개의 객체를 만들어 낼 수 있었던 것이다.

 그러면 생성자는 선언할 필요도 없는 것 아닌가라는 의문이 생길 수도 있다. 생성자의 역할은 단순히 객체를 만들어 내는데 그치지 않는다. 만약 객체를 만드는데 그친다면 다음 코드와 같은 작업을 해야한다.
 Init() 함수의 역할은 객체의 멤버변수인 num1, num2를 초기화하는 역할을 한다. 그러면 Simple 클래스의 객체를 생성하고 Init() 함수를 호출하여 초기화를 해줘야 하는 번거로운 과정을 거쳐야 한다. 이 과정을 생략할 수 있는 것이 바로 생성자를 통한 초기화이다.

 생성자도 함수 중 하나이다. 함수이기 때문에 오버로딩(overloading)이 가능하다. 함수 오버로딩을 이용하여 생성자를 통한 초기화를 해보자.
 생성자를 이렇게 변형하면 생성자를 호출할 때, 인자만 넘겨주면 된다.
이런 식으로 하면 된다. 생성과 동시에 멤버 변수과 초기화된다. Init() 함수를 따로 만들어서 호출하는 것보다 깔끔하다. 실수로 초기화를 하지 않는 실수도 방지할 수 있다.


멤버 이니셜라이저(member initializer)

 사실 객체는 크게 3단계를 거쳐서 생성된다.

  • 1단계: 메모리 공간 할당
  • 2단계: 멤머 이니셜라이저를 이용한 멤버변수의 초기화
  • 3단계: 생성자 실행

 우리는 지금까지 1단계와 3단계를 통해서 객체를 생성하였다. 2단계는 언제 적용되었는가? 적용하지 않았다. 우리는 멤버 이니셜라이저를 사용하지 않았기 때문이다.

 다음은 멤버 이니셜라이저를 통한 멤버변수 초기화를 보여준다.
 Point 클래스와 Rect 클래스 모두 멤버 이니셜라이저를 통해 초기화하고 있다. Point(const int &x1, const int &y1) : x(x1), y(y1) {} 에서 x(x1)의 의미는 멤버변수 x를 x1으로 초기화하라는 의미이다.

 멤버 이니셜라이저를 이용한 멤버변수 초기화는 생성자를 통한 초기화에 비해서 두 가지 장점이 있다고 한다. 하나는 초기화의 대상을 명확히 알 수 있다는 점이고, 다른 하나는 성능에 약간의 이점이 있다는 점이다. 장점에 대해서는 언급만 하고 넘어가도록 하겠다.


댓글 없음:

댓글 쓰기