[Effective C++] #6 생성자, 소멸자, 복사 생성자, 복사 대입 연산자
Scott Meyers의 "Effective C++"를 통해, C++ 구현에 필요한 개념들을 이해하고, 기록하기 위함입니다. 해당 항목은 2장 "생성자, 소멸자 및 대입 연산자", 항목 6 "컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 막아 버리자"에 해당하는 내용입니다.
사용자 정의 멤버 함수
class Assets {...};
Assets h1;
Assets h2;
Assets h3 (h1);
Assets h3 = h2;
세상에 모든 자산은 한 개씩 존재한다고 가정해봅시다. 각 자산마다 "Assets" 클래스를 통해 생성되며, 생성된 객체들은 서로 같을 수 없습니다. 따라서, 위 예제 코드처럼 "h3" 객체가 복사 생성자를 통해 "h1"의 값을 받거나, 복사 대입 연산자를 통해 h2의 값을 전달받을 수 없겠죠. 앞서 살펴본 내용 중 컴파일러는 클래스 생성 시 기본적으로 만들어 넣어 주는 멤버 함수들이 존재한다고 했죠. 이 중에는 복사 대입 연산자와 복새 생성자가 포함되어 있었죠. 우리는 위와 같이 자동으로 생성되는 복사 생성자와 복사 대입 연산자의 작동을 막기 위해, 직접 정의한 복사 생성자와 복사 대입 연산자를 Private 멤버로 선언합니다.
Private 멤버로 선언한 복사 대입 연산자, 복사 생성자
class Assets {
public:
...
private:
Assets(const Assets&);
Assets& operator=(const Assets&);
};
위 예제 코드의 경우, 복사 생성자와 복사 대입 연산자는 Private으로 선언되어, 컴파일러가 기본 버전을 만들 수 없게 됩니다. 더불어, Private 접근성때문에, 외부로부터 호출이 불가능해지겠죠. 이때, 중요한 점은 위 함수들이 정의 없이 선언만 했다는 겁니다. Private 멤버는 외부로부터의 접근을 완전히 차단하지만, 프렌드 함수 및 멤버 함수는 호출 할 수 있습니다. 따라서, Private 멤버로 선언을 해주되, "정의"를 안하는 겁니다.
기본 클래스에 선언한 복사 대입 연산자, 복사 생성자
class noCopy {
protected:
noCopy() {}
~noCopy() {}
private:
noCopy(const noCopy&);
noCopy& operator=(const noCopy&);
};
class Assets: private noCopy{
...
};
다른 방법으로, 링크 시점 에러를 컴파일 시점 에러로 옮길 수 있습니다. 복사 생성자와 복사 대입 연산자를 별도로 만들어진 기본 클래스의 Private 멤버로 선언하고, 이를 상속받도록 하는 겁니다.
컴파일러의 기본 함수 자동 생성 기능을 막기위해 멤버 함수를 정의하지 않고 Private으로 선언합니다. 이들을 기본 클래스에 넣어 상속받도록 하는 방법도 있습니다.
'언어 > Effective C++' 카테고리의 다른 글
[Effective C++] #8 소멸자가 던지는 예외 (0) | 2022.01.10 |
---|---|
[Effective C++] #7 기본 클래스와 가상 소멸자 (0) | 2022.01.07 |
[Effective C++] #5 생성자, 소멸자, 복사 생성자, 복사 대입 연산자 (0) | 2022.01.06 |
[Effective C++] #4 객체의 초기화 (0) | 2022.01.06 |
[Effective C++] #3_const 사용 (0) | 2022.01.05 |