2021 시작

클래스가 비어있지만 어떤 조건을 충족하면 컴파일러는 클래스를 훓고 지나갈 때 클래스에 무언가들을 만들어 낸다 그 무언가는 생성자, 소멸자,복사 생성자, 복사대입연산자 이다.

이들은 모두 public이면서 inline함수이다. 다음 코드를 보면 컴파일러가 무언가를 만들어 버리는 조건을 볼 수 있다.

//자동 생성되는 함수들
class Empty 
{
public:
	Empty() {};				//기본 생성자
	
	Empty(const Empty& rhs) {};		//복사 생성자
	~Empty() {};				//소멸자: 자동으로 생성된 소멸자는
						//가상으로 선언이 안되어있다.


	Empty& operator=(const Empty& rhs) {};	//복사 대입 연산자

};

//조건
Empty e1;					//기본 생성자, 그리고
						//소멸자

Empty e2(e1);					//복사 생성자

//e2 = e1;					//복사 대입 연산자*/

 

하지만 다음에 나올 코드 같이 하면 자동으로 생성자가 생기는 것을 막을 수 있다.

template <typename T>
class test
{
private:
	std::string nameValue;
	T objectValue;

public:
	test(const char* name, const T& value);
	test(const std::string& name, const T& value);

};

 

그냥 별거 없다. 이 템플릿 안에는 다른 생성자를 직접 정의해버리면 기본 생성자는 자동으로 생기지 않는다.(템플릿은 그냥 예제가 템플릿으로 나와서 이렇게 했지 안해도 똑같더라) 하지만 여기에 선언되지 않았기 때문에 복사 생성자와 복사대입연산자는 자동으로 생성이된다.

그리고 아까 조건이라고 말한 거 기억하는가? 사실 하나의 조건이 또 있다. 최종코드가 적법하는가와 이치에 닿는가? 이다 하나라도 안된다면 바로 오류가 뜬다. 예시를 봐보자

template<class T>
class NamedObject 
{
public:
	//이 생성자는 이제 상수 타입의 name을 취하지 않습니다. namevalue가
	//비상수 string의 참조자가 되었기 때문입니다. 참조할 string을 가져야 하기
	//때문에 char*는 없애 버렸습니다.
	NamedObject(std::string& name, const T& value);

								//위의 경우와 마찬가지로 operator=는 
								//선언된 게 없다고 사정합니다.
private:
	std::string& nameValue;		//이제 이 멤버는 참조자입니다.
	const T objectValue;		//이제 이 멤버는 상수입니다.

};


	std::string newDog("Persephone");
	std::string oldDog("Satch");

	NamedObject<int>p(newDog, 2);
	NamedObject<int>s(oldDog, 36);

	p = s;

 

이것이 왜 안될거 같은가? 멤버 변수가 const와 &(참조)형식이다 이 둘의 공통점은 한번 값이 들어가면 바뀌지 않는다는 것이다. 그러니 이럴때는 복사대입연산자를 직접 자기가 원하는대로 직접 구현해야한다.

 

그리고 또 한가지 부모의 복사 생성자를 private로 올리면 파생클래스는 암묵적인 복사생성자가 생기지않는다.

 

이것만은 잊지 말자!

1. 컴파일러는 경우에 따라 클래스에 대해 기본 생성자, 복사 생성자, 복사 대입 연산자, 소멸자를 암시적으로 만들어 놓을 수 있다.

공유하기

facebook twitter kakaoTalk kakaostory naver band
loading