부동산 거래 프로그램을 만든다. 그래서 class HomeforSale을 만드는데, 부동산 중개 업자가 꼭 신신당부한 말이 있다. 모든 자산은 세상에 하나밖에 없다!!
그럼 HomeForSale은 사본자체를 만들 수 없게 해야 한다. 그러다 보니 HomeForSale 객체를 복사하려 하면 컴파일 에러가 뜨게 하고 싶다.
일반적으로 어떤 클래스에서 특정한 종류의 기능을 지원하지 않았으면 하는 의도를 반영할려면, 그런 기능을 제공하는 함수를 선언하지 않으면 되는데, 복사 생성자와 복사 대입 연산자의 경우는 선언하지 않으면 컴파일러가 자동으로 선언해버리는게 문제다.
해결의 열쇠 : 기본 복사 생성자, 기본 복사 대입 연산자는 public member로 선언된다!!
=> private으로 바꿔버리면 됨 => 외부에서 호출 자체가 불가능, 하지만 내부에서는 호출 가능, 또 friend 함수도 호출이 가능하다.
=> 그럼 private으로 선언하되, 정의를 하지 않으면? => 외부에서는 호출 자체가 불가능, 내부에서는 호출해봤자 undefined로 에러
선언에서는 매개변수 이름도 필요없음(type과 identifier만 컴파일러에게 알려주는 것이기 때문이다.)
이 방법에 유일한 단점이라면 내부 호출 시 undefined 에러는 링크 시점 에러라는 점이다. 에러는 syntax error가 제일 좋다.
=> 복사 생성자와 복사 대입 연산자를 private에 넣는건 동일, 이것을 HomeForSale 자체에 넣지 말고 base class를 하나 만들어서 거기에 선언해놓고, HomeForSale이 이를 상속받는 derived class로 만들어 버리는 것이다. base class 는 복사 방지만 맡는다는 특별한 의미를 부여한다.(이름을 uncopyable 등으로 지으면 좋겠다.)
이러면 HomeForSale의 맴버함수나 friend 함수에서 copy를 할려고 하면 HomeForSale에는 복사 생성자나 복사 대입 연산자가 없으니 기본 복사 생성자, 기본 복사 대입 연산자를 만들려고 할 탠데, 이때 컴파일러는 base class의 대응 버전을 호출하게 되어있다.(항목 12에서 다룸)
public = 어디서든 접근이 가능.
protected = 상속관계일 때 접근이 가능
private = 해당 클래스에서만 접근이 가능
출처: <https://hwan-shell.tistory.com/25>
그러나 public이든 private이든 protected이든 derived class의 맴버들은 base class의 private 맴버에 접근 자체가 불가능함 => 링크 시점 에러가 아닌, 컴파일 시점 에러가 난다.
몇가지 짚고 넘어가자면, public으로 상속받든 private으로 상속받든 상관없는데, 이러면 굳이 public보단 private이 낫다.
또한 Uncopyable이 소멸자는 가상 소멸자가 아니어도 된다.(항목 7 참조)
또한 Uncopyable 클래스는 데이터 맴버가 전혀 없기 때문에, 항목 39에서 공부 할 기본 클래스 최적화(empty base class optimization, EBO) 기법이 먹혀들 여지가 있는데, Uncopyable은 base class라 이 기법을 사용하면 다중 상속으로 갈 가능성이 있다.(항목 40 참조)
그럼 다중 상속일 때가 문제가 되는데, 이 때는 EBO가 돌아가지 못할 때가 있다.(항목 39 참조). 근데 이런건 대충 무시하고 살아도 됨. 왠만하면 의도한대로 돌아가기 때문이다.
부스트 라이브러리(항목 55 참조)를 보면 Uncopyable과 똑같은 구실을 하는 클래스가 있음(noncopyable)
- 컴파일러에서 자동으로 제공하는 기능을 하용치 않으려면, 대응되는 맴버 함수를 private으로 선언한 후 구현은 하지 않은 채로 두자. 또는 Uncopyable과 비슷한 기본 클래스를 쓰는 것도 방법이다.(링크 타임 에러를 컴파일 타임 에러로 당기는 방법임)
'Effective C++ > 2. 생성자, 소멸자 및 대입 연산자' 카테고리의 다른 글
항목 10: 대입 연자는 *this의 참조자를 반환하게 하자 (0) | 2021.04.24 |
---|---|
항목 9: 객체 생성 및 소멸 과정 중에는 절대로 가상함수를 호출하지 말자 (0) | 2021.04.24 |
항목 8: 예외가 소멸자를 떠나지 못하도록 붙들어 놓자 (0) | 2021.04.24 |
항목 7: 다형성을 가진 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자 (0) | 2021.04.24 |
항목 5: C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자. (0) | 2021.04.24 |