C++

생성자

춤추는수달 2021. 12. 27. 19:57
class Man{
public :
	Man(); // 기본생성자
  Man(const Man& m); //복사 생성자
  Man(int hp);//타입변환 생성자
	Man(int hp, int name); //기타 생성자
}

기본생성자

아무런 인자도 받지 않는 생성자.

아무런 생성자도 만들어주지 않을 경우 복사 생성자와 함께 자동으로 암시적 생성된다. 명시적 선언도 가능.

아래와 같이 사용한다.

Man m; //자동으로 기본 생성자 호출

복사 생성자

자신과 같은 타입의 클래스를 인자로 받는 생성자.

아무런 생성자도 만들어주지 않을 경우 기본 생성자와 함께 자동으로 암시적 생성된다. 명시적 선언도 가능.

인자로 받은 객체와 모든 멤버 데이터가 같은 객체를 만든다.

아래와 같이 사용한다.

Man m1;
Man m2(m1);// 복사 생성자 호출. m1과 m2는 멤버 변수가 모두 같은 값임.
Man m3 = m2; //이렇게 바로 대입해도 복사 생성자가 호출된다.

Man m4;
m4 = m3; //이런 경우에는 복사 생성자 호출되지 않음. 그냥 생성한 뒤 복사하기임.

기타 생성자

기본 생성자와 복사 생성자를 제외한 기타 다른 생성자들 이다. 인자를 한개 이상 받는다.

타입변환 생성자

기타 생성자 중 인자를 한 개만 받는 생성자. 이름처럼 마치 타입 변환을 하듯이 동작한다.

그냥 기타생성자라고 생각할 수도 있지만 아래처럼 값을 대입해도 호출된다;;

 

Man m1;
m1 = 1; // Man(int hp) 타입변환 생성자 호출.
Man m2 = 2; // Man(int hp) 타입변환 생성자 호출.
Man m3(3);  // Man(int hp) 타입변환 생성자 호출.
void CallMan(Man man){
	cout << "hi man";
}

CallMan(2); // 자동으로 타입변환 생성자를 호출해서 CallMan함수에 넘겨줘버림;;

 

그러나 이는 의도하지 않은 상황을 만들기 쉽기 때문에 위와 같이 호출되는 상황을 막을 수 있는 방법을 제공한다. 그것은 explicit이다.

 explicit Man(int hp);//명시적 타입변환 생성자.

CallMan(2); //위처럼 선언하면 이 문장은 에러가 발생함.
CallMan((Man)2); //그러나 이처럼 명시적으로 타입변환을 해주면 타입변환 생성자가 문제없이 호출됨.

선처리 영역

선처리영역이란 생성자를 호출하고 내용을 처리하기 전에 실행되는 부분으로 코드가 없이 자동으로 실행되는 부분을 말한다. 선처리 영역에선 부모생성자, 소유 객체의 생성자 등을 호출해준다.

부모 생성자

상속받은 부모의 기본생성자를 자식의 생성자의 맨 앞에서 자동적으로 호출한다.

그러나 다음과 같은 문법을 사용하면 부모의 기본생성자가 아닌 다른 생성자를 지정해서 호출하게 할 수 있다.

class Man : class Bio{
	public Man() : Bio(10){
	}	
}

소유한 클래스의 생성자

소유한 클래스의 생성자도 부모 생성자와 마찬가지로 생성자의 선처리영역에서 자동 호출된다. 따라서 아래처럼 생성자 안에서 소유한 객체를 초기화해주면 Cat의 생성자가 두 번 호출되기 때문에 비효율적이다.

class Man : class Bio{
	public Man() : Bio(10), {// Cat()이 호출됨
		cat = Cat(10); //생성자 내에서 객체 초기화
	}	

	public Cat cat;//소유한 Cat 객체
}

이 문제를 해결하려면 아래처럼 부모 생성자를 지정해준 것과 같이 소유한 객체의 생성자를 지정해주면 된다.

class Man : class Bio{
	public Man() : Bio(10), Cat(10) {// Cat()이 호출됨
	}	

	public Cat cat;//소유한 Cat 객체
}

초기화 리스트.

초기화 리스트는 위에서 본 부모생성자를 지정해주는 것 처럼 생성자의 오른쪾에 : 기호를 붙이고 선언하게 된다. 여기서는 각종 멤버 변수들을 초기화할 수 있다. 물론 멤버 변수는 다른 방법으로도초기화 해줄 수 있지만 초기화 리스트를 사용해야만 하는 상황도 있다. 바로 레퍼런스(&)변수와 상수 변수(const)이다. 이들은 반드시 선언과 동시에 초기화를 해야하는데, 생성자 내에서 초기화 하려고 하면 선언된 뒤에 초기화 되는 것이므로 불가능하다. 따라서 초기화 리스트에서 초기화를 해준다.

class Man : class Bio{
	public Man() : Bio(10), hp(100), hp2(200), hp3(300) {
		//hp2 = 100;이건 안됨

	}	

	public :
		int hp;
		int& hp2;
		const int hp3;
}

 

'C++' 카테고리의 다른 글

메모리 모델  (0) 2022.02.01
Futrue  (0) 2022.01.27
조건 변수(Condition Variable)  (0) 2022.01.27
멀티 쓰레드 Lock 구현  (0) 2022.01.26
멀티 쓰레드  (0) 2022.01.24