객체 생성과 동시에 멤버들의 초기화를 해준다.
class SimpleClass{
int num1;
Object obj;
public:
SimpleClass(int a, Object &obj) // <- 생성자
{
num1 = a;
this->obj = obj;
}
}
생성자는
- class이름과 똑같이 선언해야한다.
- 반환형 X
- 오버로딩 가능
- 디폴트 값 설정가능
생성자가 선언된 class로 객체를 생성할때
Object *obj = new Object;
ClaName test1(5, *obj); // 방법 1
ClaName * test2 = new ClaName(5, *obj); // 방법 2
와 같이 전역,지역변수로 선언할때와 동적할당에서 두가지 형태가 있다.
class SimpleClass
{
private:
int num1;
int num2;
public:
SimpleClass() // case1
{
num = 0;
num = 0;
}
SimpleClass(int n) // case2
{
num = n;
num = 0;
}
SimpleClass(int n1, int n2) // case3
{
num = n1;
num = n2;
}
/*
SimpleClass(int n1 = 0, int n2 = 0) // case4
{
num = n1;
num = n2;
}
*/
case4를 주석처리한 이유는
SimpleClass * sim = new SimpleClass();
로 객체 생성시 case1과 case4 중 무엇을 호출할지 모호성이 생기기 때문이다. 이는 기본함수에서도 생기는 문제이므로 오버로딩과 디폴트값을 동시에 쓸 때는 오류를 조심해야한다.
매개변수가 없는 생성자의 호출시
SimpleClass * sim();
<- 불가능
SimpleClass * sim;
<- 가능
SimpleClass * sim = new SimpleClass;
<-가능
SimpleClass * sim = new SimpleClass();
<-가능
첫번째가 불가능한 이유는 함수정의와 선언이 똑같기 때문이다. 위와 같이 선언한다면 함수의 정의라고 컴파일러가 인식한다.
class SimpleClass{
int num1;
Object obj;
Point center;
public:
SimpleClass(int a, Object &obj, int b, int c) :num1(a), center(b, c)(// <- 멤버 이니셜라이저
{
this->obj = obj;
//비우는 경우많음
}
}
이니셜라이저는 함수 정의부에만 있으면 된다.
:center(b, c)
가 의미하는 바는
"객체 center의 생성과정에서 인자 b, c를 받는 생성자를 호출해서 생성하라"
:num1(a)
가 의미하는 바는
"num1 = a"
생성자 몸체를 통한 초기화는
int num1;
num1 = a;
이러한 차이로 이니셜라이저를 통한 초기화는 성능상 약간의 이점 과 const멤버변수, 참조자 멤버변수의 초기화에 이용할 수 있다.
객체의 생성과정
- 메모리공간의 할당
- 이니셜라이저를 이용한 멤버변수 초기화
- 생성자 몸체 실행
만약 생성자를 따로 정의하지 않았다면 생성자가 없다고 생각할 수도 있지만 기본 생성자가 만들어져 있다.
class Simple
{
}
/* 두 class는 동일하다.
class Simple
{
public:
Simple()
{
}
}
*/
만약 생성자를 하나라도 선언한다면 디폴트 생성자는 사라지므로 유의해야한다.
객체가 소멸될 때 호출된다.
class SimpleClass{
int num1;
Object obj;
public:
SimpleClass(int a, Object &obj) // <- 생성자
{
num1 = a;
this->obj = obj;
}
~SimpleClass() <- 소멸자
{
}
}
- ~ + Class이름으로 선언된다.
- 반환형 x
- 매개변수 x, 따라서 디폴트값, 오버로딩 설정 불가
- 디폴트 소멸자가 있다.
보통 객체 초기화 시 동적할당을 했다면 이를 해제하기 위해 사용된다.