[ Effective C++ ] 정리 모음집
" C++ 프로그래머의 필독서, 스콧 마이어스의 Effective C++ 를 읽고 내용 요약 / 정리 "
" 제목이 곧 핵심! "
- 호환되는 모든 타입을 받아들이는 멤버 함수를 만들려면 멤버 함수 템플릿을 사용하자!
- 일반화된 복사 생성 연산과 일반화된 대입 연산을 위해 멤버 템플릿을 선언했다 하더라도, 보통의 복사 생성자와 복사 대입 연산자는 여전히 직접 선언해야 한다!
calss Top { ... };
class Middle : public Top { ... };
class Bottom : public Middle { ... };
Top* pt1 = new Middle; // Middle* >> Top*의 암시적 변환
Top* pt2 = ndw Bottom; // Bottom* >> Top*의 암시적 변환
const Top* pct2 = pt1; // Top* >> const Top*의 암시적 변환
파생 클래스 포인터는 암시적으로 기본 클래스 포인터로 변환된다
비상수 객체에 대한 포인터는 상수 객체에 대한 포인터로 임시적 변환이 가능하다
template<typename T>
class SmartPtr
{
public:
explicit SmartPtr(T* realPtr);
...
};
SmartPtr<Top> pt1 = SmartPtr<Middle>(new Middle);
SmartPtr<Top> pt2 = SmartPtr<Bottom>(new Bottom);
SmartPtr<const Top> pct2 = pt1;
SmartPtr<Middle>
과 SmartPtr<Top>
은 완전히 별개의 클래스class BelowBottom : public Bottom { ... };
template<typename T>
class SmartPtr
{
public:
template<typename U>
SmartPtr(const SmartPtr<U>& otehr);
...
};
템플릿을 인스턴스화 해 '무제한' 개수의 함수를 만들어 냄
위 생성자를 일반화 복사 생성자라고 부른다
- 같은 템플릿을 써서 인스턴스화 되지만 타입이 다른 타입의 객체로 부터 원하는 객체를 만들어 주는 생성자
explicit 키워드를 사용하지 않음으로써 암시적 변환 허용
📢 하지만 이 행동으로 인해 원하지 않는 동작도 수행한다..
(SmartPtr<Top>
에서 SmartPtr<Bottom>
변환, SmartPtr<int>
에서 SmartPtr<double>
변환 등)
template<typename T>
class SmartPtr
{
public:
template<typename U>
SmartPtr(const SmartPtr<U>& otehr)
: heldPtr(other.get()) { ... }
T* get() const { return heldPtr; }
...
private:
T* heldPtr;
};
template<class T> class shared_ptr
{
public:
template<class Y>
explicit shared_ptr(Y* p);
template<class Y>
shared_ptr(shared_ptr<Y> const& r);
template<class Y>
explicit shared_ptr(weak_ptr<Y> const& r);
template<class Y>
explicit shared_ptr(auto_ptr<Y>& r);
template<class Y>
shared_ptr& operator=(shared_ptr<Y> const& r);
template<class Y>
shared_ptr& operator=(auto_ptr<Y>& r);
...
};
일반화 복사 생서자 외 모든 생성자는 explicit 로 선언
- shared_ptr로 만든 어떤 타입으로부터 또 다른(shared_ptr로 만든) 타입으로 진행되는 암시적 변환은 허용되지만 기본제공 혹은 다른 스마트 포인터 타입으로부터 변환되는 것은 막겠다는 뜻, 명시적 변환은 허용 한다.
생성자와 대입 연산자에 넘겨지는 auto_ptr은 const로 선언하지 않음
- 복사 연산으로 객체가 수정되면 소유권이 복사된 객체 하나만 가져야 하는 auto_ptr의 특성을 반영
- weak_ptr은 cosnt로 선언 함
- 템플릿은 "컴파일러는 프로그래머가 직접 선언하지 않으면 자동으로 함수(생성자, 복사생성자 등) 를 만든다." 라는 언어의 규칙을 바꾸지 않는다.
- 일반화 복사 생성자의 선언은 자동으로 만들어지는 복사 생성자를 막는 행위가 아니다.
📢 따라서 보통의 복사 생성자 까지 직접 구현해 줘야 한다!
template<class T> class shared_ptr
{
public:
shared_ptr(shared_ptr const& r);
template<calss Y>
shared_ptr(shared_ptr<Y> const& r);
shared_ptr& operator=(shared_ptr const& r);
template<calss Y>
shared_ptr& operator=(shared_ptr<Y> const& r);
...
};