[Effective C++] 항목 6 : 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해 버리자

수민이슈·2023년 3월 15일
0

Effective C++

목록 보기
6/30
post-thumbnail

스콧 마이어스의 Effective C++을 읽고 개인 공부 목적으로 요약 작성한 글입니다!

💡 컴파일러에서 자동으로 제공하는 기능을 허용하지 않으려면,
대응되는 멤버함수를 private으로 선언한 후에 구현은 하지말자!
UnCopyable과 비슷한 기본 클래스를 쓰고 상속 받는 것도 괜춘!


🖊️ 난 복사하고 싶지 않은데..?

복사를 하면 안되는 상황이 있다고 치자
내가 복사를 하고 싶든 하고 싶지 않든 .. 코드를 이렇게 만들면

class HomeForSale { ... };

HomeForSale h1;
HomeForSale h2;

HomeForSale h3(h1);		// 안하고싶어 ㅠㅠ제발 ㅠㅠ오류내줘...

h1 = h2;				// 얘도 안하고 싶어.. 컴파일에러 제발..

복사가 된다.... 컴파일을 막고 싶어도 막을 수가 없다.

복사 생성자복사 대입 연산자선언하지 않고 외부에서 호출하려 하면 컴파일러가 선언해주기 때문이다


🖊️ 그래서 어떡하쥬?

멤버 함수를 private으로 선언하고 정의하지 말자

복사 생성자나 복사 대입 연산자를 private 멤버로 만들자.
그러면 일단 클래스 멤버함수가 선언된거기 때문에, 컴파일러는 혼자 또 기본버전을 만들 수는 없다.
private 멤버니까 외부에서 호출할 수 없다

하지만,,
해당 클래스의 멤버 함수나, friend 함수는 복사생성자나 복사 대입 연산자를 호출할 수 있게 된다.

정의를 하지 않아버리면 된다.
이 상황에서 복사 생성자나 복사 대입 연산자를 호출한다?
절대 컴파일 되지 않을거다

class HomeForSale {
public:
	...
private:
	...
    HomeForSale(const HomeForSale&);
    HomeForSale& operator= (const HomeForSale&);
    // private으로 선언만 하고 정의는 안했다!
};

기본 클래스를 사용해보자

복사 방지 역할을 담당하는 클래스를 만든다.

class UnCopyable {
protected: 						// UnCopyable을 상속받아 쓸거니까
	UnCopyable() {}
    ~UnCopyable() {}
    
    // 생성과 소멸은 허용하니까 Protected로
    
private:
	UnCopyable(const UnCopyable&);
    UnCopyable& operator= (const UnCopyable&);
    
    // 복사는 안되게 할거니까 Private로 하고 정의는 안함
};

그리고 이제 복사를 막고 싶은 HomeForSale클래스를 UnCopyable의 파생클래스로 정의한다.

class HomeForSale : private UnCopyable {
	...
};

이제 그러면
생성, 소멸은 잘 되고 복사는 안될거다.

컴파일러가 생성한 복사 생성자, 복사 대입 연산자는 기본 클래스의 대응 버전을 호출하게 되어 있다.
근데 지금은 기본 클래스에서 private로 되어 있기 때문에 불가능하다!!!

UnCopyable로부터 Private으로 상속받으면,
상위 클래스에서 Public과 Protected로 선언된 함수들을 Private로 접근할 수 있다.
Public으로 상속 받을 필요가 없당

이렇게 하면 링크 시점 에러컴파일 시점 에러로 옮길 수 있다!!

이건 그냥 구현한 거고, Boost에 noncopyable 클래스가 있다~


😊느낀점

정말 상상도 못한 내용이다
어렵진 않은데 필요한 내용이다.
항상 public 상속만 쓰다보니, private 상속과 protected 상속에 대해서도 한 번 더 공부했다.

0개의 댓글