항목 6 : 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해 버리자
코딩을 하다보면 객체의 복사를 막고 싶은 경우가 있습니다.
하지만 복사 생성자나 복사 대입 연산자를 선언하지 않으면 컴파일러가 저절로 만들어 낼지도 모릅니다.
그렇다고 직접 선언하면 복사하는 것은 마찬가지입니다.
이를 해결하기 위한 방법은 복사 생성자 및 복사 대입 연산자를 private 멤버로 선언하는 것입니다.
여기에도 부족한 것이 있습니다.
private 멤버 함수는 그 클래스의 멤버함수 및 프렌드 함수가 호출할 수 있다는 점이죠.
이것까지 막으려면, '정의'를 안 해 버리는 방법이 있습니다.
정의되지 않은 함수를 누군가가 어쩌다 실수로 호출하려 했다면 분명히 링크 시점에 에러를 보지게 될 테니 괜찮습니다.
1
2
3
4
5
6
7
8
|
class HomeForSale{
public:
...
private:
...
HomeForSale(const HomeForSale&);
HomeForSale& operator=(const HomeForSale&);
};
Colored by Color Scripter
|
HomeForSale 클래스는 이렇게 정의되었습니다.
한 가지 팁이 있습니다.
링크 시점 에러를 컴파일 시점 에러로 옮길 수도 있습니다(에러 탐지는 나중으로 미루는 것보다 미리 하는 것이 좋습니다.)
복사 생성자와 복사 대입 연산자를 private로 선언하되, 이것을 HomeForSale 자체에 넣지 말고 별도의 기본 클래스에 넣고 이것으로부터 HomeForSale을 파생시키는 것입니다. 그리고 그 별도의 기본 클래스는 복사 방지만 맡는다는 특별한 의미를 부여합니다.
1
2
3
4
5
6
7
8
9
|
class Uncopyable{
protected: // 파생된 객체에 대해서
Uncopyable() { } // 생성과 소멸을
~Uncopyable() { } // 허용합니다.
private:
Uncopyable(const Uncopyable&); // 하지만 복사는 방지합니다.
Uncopyable& operator=(const Uncopyable&);
};
Colored by Color Scripter
|
복사를 막고 싶은 HomeForSale 객체는 이제 이렇게 바꿔 봅시다. Uncopyable로부터 상속받게 하고 그냥 내버려 두는 것으로 끝입니다.
1
2
3
|
class HomeForSale : private Uncopyable{ // 복사 생성자도,
... // 복사 대입 연산자도
}; // 이제는 선언되지 않습니다.
|
마지막으로 Uncopyable의 구현과 사용법에 대해 기술적으로 미묘한 부분 몇 가지를 지적하고 이번 항목을 마무리 할까 합니다.
Uncopyable로부터의 상속은 public일 필요가 없습니다. 그리고 Uncopyable의 소멸자는 가상 소멸자가 아니어도 됩니다. 또한 Uncopyable 클래스는 데이터 멤버가 전혀 없기 때문에 공백 기본 클래스 최적화 기법이 먹혀 들어갈 여지도 있습니다.
하지만 Uncopyable 클래스는 기본 클래스이기 때문에 이 기법을 사용하면 다중 상속으로 갈 가능성이 있습니다. 이번에는 다중 상속이 문제가 되는데, 다중 상속 시에는 공백 기본 클래스 최적화가 돌아가지 못할 때가 종종 있습니다. 이런 미묘한 부분은 어지간해선 대강 무시하고 살아도 아무 상관이 없습니다.
꼭 잊지 말아야 할 것!
1. 컴파일러에서 자동으로 제공하는 기능을 허용치 않으려면, 대응되는 멤버 함수를 private로 선언한 후에 구현은 하지 않은 채로 두십시오.
2. Uncopyable과 비슷한 기본 클래스를 쓰는 것도 한 방법입니다.
'언어 > C++' 카테고리의 다른 글
[Effective C++] 예외가 소멸자를 떠나지 못하도록 붙들어 놓자 (0) | 2020.01.08 |
---|---|
[Effective C++] 다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자 (0) | 2020.01.07 |
[Effective C++] C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자 (0) | 2020.01.05 |
[Effective C++] 객체를 사용하기 전에 반드시 그 객체를 초기화하자 (0) | 2020.01.04 |
[Effective C++] 낌새만 보이면 const를 들이대 보자! (0) | 2020.01.03 |