[Effective C++] 6. 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해 버리자
728x90
반응형
복사 생성자와 복사 대입 연산자를 사용하고 싶지 않을 때
항목 5에서 컴파일러가 은근슬쩍 만들어내는 함수들에 대해 알았으니, 이러한 함수들을 사용하고 싶지 않을 때에 대해서 알아보자.
첫 번째 해결의 열쇠는 다음과 같다. 컴파일러가 생성하는 함수들은 모두 public멤버가 되지만, 직접 선언할 때는 public멤버로 선언해야 한다고 요구하는 부분은 없다는 점이다.
즉, 복사 생성자 및 복사 대입 연산자를 private 멤버로 선언하면
- 클래스 멤버 함수가 명시적으로 선언되기 때문에 컴파일러는 자신의 기본 버전을 만들 수 없음
- private의 접근성을 가지므로 외부로부터 호출도 불가능하여 복사를 할 수 없음
두 가지 이유로 인해 외부에서 복사는 불가능하게 할 수 있다.
하지만 private멤버 함수는 그 클래스의 멤버 함수 및 friend 함수가 호출할 수 있다는 점에서 허점이 존재하는데, 이것은 정의를 안 하는 방법으로 해결할 수 있다.
정의를 안 하는 방법은 아래와 같은데,
class HomeForSale
{
public:
...
private:
HomeForSale(const HomeForSale&); // 선언
HomeForSale& operator=(const HomeForSale&);
}
이제 외부에서 복사 생성자 및 복사 대입 연산자를 호출한다면(클래스 내부나 friend함수 외엔 호출도 못하겠지만), 정의되지 않은 함수를 호출하는 것이므로 링크 시점에 에러를 발생시킬 것이다.
하나 더 덧붙이자면, 에러 탐지는 미리 하는 것이 좋으므로 링크 시점 에러를 컴파일 시점 에러로 옮겨보자.
방법은 간단하다.
복사 생성자와 복사 대입 연산자를 private로 선언하되, 이것을 HomeForSale 자체에 넣지 말고 별도의 기본 클래스에 넣고 이 클래스로부터 HomeForSale을 파생시키는 것이다. 그리고 그 별도 클래스는 복사 방지만 맡는다.
class Uncopyable
{
protected:
Uncopyable();
~Uncopyable();
private:
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
}
class HomeForSale: private Uncopyable
{
}
이렇게 Uncopyable을 상속받은 HomeForSale 클래스는 이제 복사 생성자도 복사 대입 연산자도 선언되지 않는다.
Uncopyable의 구현과 사용법
- Uncopyable로부터 상속은 public일 필요성이 없다.
- Uncopyable의 소멸자는 가상 소멸자가 아니어도 된다.
- Uncopyable클래스는 데이터 멤버가 전혀 없기 때문에 공백 기본 클래스 최적화 기법이 먹혀 들어갈 여지도 있다.
- 하지만 Uncopyable 클래스는 기본 클래스이기 때문에 이 기법을 사용 시 다중 상속으로 갈 가능 성도 있음
- 다중 상속 시 공백 기본 클래스 최적화가 돌아가지 못할 때가 있음
- 부스트 라이브러리를 보면 Uncopyable과 똑같은 구실을 하는 클래스가 있는데 이것을 써도 된다. (noncopyable 클래스)
요약
- 컴파일러에서 자동으로 제공하는 기능을 허용치 않으려면, 대응되는 멤버 함수를 private로 선언한 후에 구현은 하지 않은 채로 두면 된다. Uncopyable과 비슷한 기본 클래스를 쓰는 것도 방법이다.
728x90
반응형
'Books > Effective C++' 카테고리의 다른 글
[Effective C++] 8. 예외가 소멸자를 떠나지 못하도록 붙들어 놓자 (0) | 2022.05.14 |
---|---|
[Effective C++] 7. 다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자 (0) | 2022.05.13 |
[Effective C++] 5. C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자 (0) | 2022.05.08 |
[Effective C++] 4. 객체를 사용하기 전에 반드시 그 객체를 초기화하자 (0) | 2022.05.07 |
[Effective C++] 3. 낌새만 보이면 const를 들이대 보자! (0) | 2022.05.07 |
댓글
이 글 공유하기
다른 글
-
[Effective C++] 8. 예외가 소멸자를 떠나지 못하도록 붙들어 놓자
[Effective C++] 8. 예외가 소멸자를 떠나지 못하도록 붙들어 놓자
2022.05.14 -
[Effective C++] 7. 다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자
[Effective C++] 7. 다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자
2022.05.13 -
[Effective C++] 5. C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자
[Effective C++] 5. C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자
2022.05.08 -
[Effective C++] 4. 객체를 사용하기 전에 반드시 그 객체를 초기화하자
[Effective C++] 4. 객체를 사용하기 전에 반드시 그 객체를 초기화하자
2022.05.07