객체의 속성(즉, 데이터 멤버)은 객체의 현재 상태를 나타내는 값이다. 그러므로 처음 객체가 만들어졌을 때에는 그 객체의 초기 상태를 적절히 지정하여 두어야 한다.
반드시 수행해야 하는 초기화 과정을 실수로 누락하면 프로그램은 올바로 동작하지 않는다. 이러한 실수가 발생하지 않도록 초기화 과정을 자동화할 수 있다면 불필요한 에러를 유발하지 않을 수 있다. 이러한 목적으로 사용할 수 있는 것이 생성자(constructor)이다. 생성자는 객체가 생성될 때 수행할 작업을 정의하는 특수한 멤버함수로서, 객체를 정의하는 문장에 의해 자동적으로 호출된다.
생성자의 선언
생성자의 기본적인 선언 형식은 다음과 같다.
class ClassName{ ...... public: ClassName(fParameterList){ // 생성자 ...... } ...... }; |
생성자는 기본적으로 일반 멤버함수와 유사하다. 매개변수를 통해 인수를 전달받을 수 있으며, 여러 가지 방법으로 사용될 수 있도록 생성자를 다중정의할 수도 있다. 그러나 다음과 같이 생성자만의 고유한 사항도 있다.
- 생성자는 클래스의 이름을 사용하여 선언한다.
- 생성자의 머리부에는 반환 자료형을 표시하지 않는다. 또한 몸체 내에서 return 명령으로 값을 반환할 수 없다(이 경우 일반 함수에서는 머리부의 반환 자료형에 void라고 표기하나. 생성자에서는 반환 자료형을 표기하지 않음).
- public으로 선언한 생성자만 클래스 외부에서 객체를 만드는 데 사용할 수 있다.
초기화 리스트
생성자가 하는 주요 작업으로는 데이터 멤버에 적절한 초깃값을 넣는 것이다. 생성자에서 데이터 멤버의 값에 초깃값을 대입하는 것은 초기화 리스트(initializer list)를 이용하여 간결하게 표현할 수 있다.
초기화 리스트는 함수의 머리에 콜론 ( : )을 기입하과 '변수명[초깃값]' 또는 '변수명(초깃값)' 형태로 초깃값을 지정한 것이다. 만일 초기화 항목이 여러개 있을 때에는 쉼표( , )로 구분한다.
데이터 멤버의 값을 초기화하는 간단한 작업의 경우 초기화 리스트를 통해 처리하는 것이 일반적이다. 초기화와 대입은 결과적으로 동일한 것처럼 보이지만, 실제로는 차이가 있다. 초기화는 그 대상이 만들어질 때 값이 지정되는 것이고, 대입 명령은 이미 만들어져 있는 대상에 값을 넣는 것이다. 예를 들어 const로 지정된 상수는 초기화를 통해 값을 지정할 수는 있지만, 대입 명령을 이용하여 상수에 값을 지정할 수는 없다.
[소스코드 4-6]의 CounterM 클래스는 최댓값이 제한된 계수기를 만들기 위한 것이다. 매개변수를 통해 전달되는 최댓값까지 계수를 한 후 다시 계수를 하면 0으로 돌아가도록 count() 함수를 정의한 것을 볼 수 있다.
// 소스코드 4-6 : CounterM.h
#pragma once
#ifndef COUNTERM_H_INCLUDED
#define COUNTERM_H_INCLUDED
class CounterM { // 클래스 CounterM의 선언 시작
const int maxValue; // 계수기의 최댓값
int value; // private 데이터 멤버
public: // public 멤버함수
CounterM(int mVal) : maxValue{mVal}, value{0} {} // 생성자
void reset() { // 계수기의 값을 0으로 지움
value = 0;
}
void count() { // 계수기의 값을 1 증가시킴
value = value < maxValue ? value + 1 : 0;
}
int getValue() const { // 계수기의 현재 값을 반환함
return value;
}
};
#endif // !COUNTERM_H_INCLUDED
const int maxValue;는 maxValue라는 데이터 멤버를 선언하여 계수기 객체의 최댓값을 저장하게 하였는데, 각각의 계수기 객체의 최댓값은 객체가 생성된 후 변하지 않도록 하기 위해 const를 지정하고 있다.
CounterM 생성자는 계수기의 최댓값을 매개변수를 통해 전달받는데, 초기화 리스트를 사용하여 이 값으로 maxValue라는 const 멤버를 초기화하는 것을 볼 수 있다. 그러나 만일 위의 CounterM 생성자 대신
CounterM(int mVal){ value = 0; maxValue = mVal; // ① } |
와 같이 생성자를 선언하면 문법 에러가 발생할 것이다. maxValue가 const로 지정되어 있어서 ①과 같이 값을 대입할 수 없기 때문이다. 그러므로 이러한 경우는 초기화 리스트를 사용하여야 한다.
[소스코드 4-7]은 CounterM 클래스의 객체를 생성하여 사용하는 예를 보여주는 프로그램이다.
// 소스코드 4-7 : CntMMain.cpp
#include <iostream>
#include "CounterM.h"
using namespace std;
int main() {
CounterM cnt(9); // Counter 객체의 정의
cout << "계수기의 현재 값:" << cnt.getValue() << endl;
for (int i = 0; i < 12; i++) {
cnt.count(); // 계수기를 1 증가시킴
cout << "계수기의 현재 값:" << cnt.getValue() << endl;
}
return 0;
}
====== 결과 ======
계수기의 현재 값:0
계수기의 현재 값:1
계수기의 현재 값:2
계수기의 현재 값:3
계수기의 현재 값:4
계수기의 현재 값:5
계수기의 현재 값:6
계수기의 현재 값:7
계수기의 현재 값:8
계수기의 현재 값:9
계수기의 현재 값:0
계수기의 현재 값:1
계수기의 현재 값:2
CounterM 클래스의 생성자는 1개의 int 값이 인수로 전달되어야 하므로 CounterM cnt(9); 와 같이 객체를 선언할 때 이에 해당되는 실 매개변수를 포함해야 한다. 반복문을 사용하여 12회 계수를 하며 계수기의 값을 출력한다. 최댓값인 9까지 계수하고 난 후 다시 계수를 하면 0으로 리셋되는 것을 볼 수 있다.
'Programming Languages > C++' 카테고리의 다른 글
[클래스와 객체]-생성자의 종류-디폴트 생성자 (0) | 2020.06.13 |
---|---|
[클래스와 객체]-생성자와 소멸자-소멸자 (0) | 2020.06.10 |
[클래스와 객체]-클래스 선언과 객체 정의 (0) | 2020.06.07 |
[클래스와 객체]-객체지향 프로그래밍의 주요 개념 (0) | 2020.06.06 |
[함수]-inline 함수 (0) | 2020.06.05 |