모어 이펙티브 c++ 5장 스터디

10
More Effective C++ 5

Upload: quxn6

Post on 23-Jun-2015

140 views

Category:

Software


5 download

DESCRIPTION

모어 이펙티브 c++ 5장 스터디

TRANSCRIPT

Page 1: 모어 이펙티브 c++ 5장 스터디

More Effective C++ 5

Page 2: 모어 이펙티브 c++ 5장 스터디

유용하고 재미있는 기법들

Page 3: 모어 이펙티브 c++ 5장 스터디

생성자와 비 멤버 함수를 가상함수처럼 동작하게 만들기

가상 생성자자신이 받은 입력 데이터에 의존하여 다른 타입의 객체를 생성하는 함수ex ) NLComponent 를 상속한 TextBlock, Graphic 클래스가 있을 때 , 이를 사용하는 NewLetter 클래스에서 아래와 같이 ..

static NLCompnent * readComponent(istream& str);

NewLetter::NewLetter(istream& str) {

components.push_back(readComponent(str));

}

readComponent 의 str 내용에 따라 Textblock 을 생성할지 Graphic 를 생성할 지 결정 .

가상 복사 생성자NLComponent 에 clone() 같은 가상함수를 만들고 상속받은 클래스에서 return type 만 달리하는 동일한 함수 clone() { return new TextBlock(*this) } 혹은 new Graphic(*this)) 을 구현

비멤버함수를 가상함수처럼 ..원하는 일을 하는 가상함수를 만들고 비 가상함수에서 이를 호출

Page 4: 모어 이펙티브 c++ 5장 스터디

클래스 인스턴스의 개수를 의도대로 제한하는 방법

객체를 전혀 생성하지 않거나 하나만 만들기1. 생성자를 private 으로 한다 .

2. static 으로 선언된 자신의 객체를 갖는다 .

3. 비멤버 friend 호출 함수를 통해 위에서 만든 객체를 불러온다 .

* 정적 객체가 클래스 안에 있으면 사용 여부와 상관없이 생성 , 함수에 있으면 호출시점에 생성 .

* 비 멤버함수의 inline 은 내부 연결을 가지고 이런 함수는 목적 코드에서 중복 생성될 수 있다 .

객체 생성이 이루어지는 세 가지 상황numObject 등의 내부 변수를 통해서 객체의 수를 관리할 수도 있음 .

생성자에서 ++ 하고 소멸자에서 -- 하는 방식으로 .

하지만 이럴 경우 1) 자신의 객체를 생성할 때 , 2) 클래스를 상속받거나 3) 다른 클래스의 멤버로( 합성 ) 존재할 때도 numObject 가 증가하게 됨 .

이런 일을 방지하기 위해 4. 생성자는 private 으로 만들자5. 유사생성자 (static 함수로 자기 클래스의 포인터를 반환하는 함수 ) 를 사용하자 !

6. 이제 생성자에서 카운팅을 하자 . ( 정해진 개수가 넘으면 nullptr 를 반환하는 식으로 예외처리 )

7. numObject 는 static 멤버로 만들자 (static 멤버는 반드시 ‘정의’해야 함 )

Page 5: 모어 이펙티브 c++ 5장 스터디

클래스 인스턴스의 개수를 의도대로 제한하는 방법

인스턴스 카운팅 기능을 가진 기본 클래스객체 수를 카운팅하는 클래스가 추가로 필요하다면 위의 작업을 모두 반복해야 한다 .

이런 귀찮음은 ‘클래스 템플릿’을 통해 해결하자 .

object counting 하는 함수 , 생성자 , 소멸자 등을 템플릿으로 만들고사용해야할 클래스에서 이를 상속받는다 .

• public 으로 상속받을 경우 가상 소멸자를 사용• private 상속 시 상속받은 클래스의 public 영역에 using Counted<Printer>::objectCount

식으로 선언하면 public 처럼 쓸 수 있다 .

Page 6: 모어 이펙티브 c++ 5장 스터디

힙에만 생성되거나 힙에는 만들어지지 않는 클래스

객체가 Heap 에만 생성되게 하기생성자는 public 소멸자는 private 에 만들기 ( 생성자는 좀 많으니까 , 소멸자만 )

이 클래스를 상속할 땐 ? 소멸자를 protected 로 만들어 해결 ,

객체를 다른 클래스의 멤버로 넣을 땐 ? 객체의 포인터를 넣는걸로 해결

어떤 객체가 Heap 에 생성되었는지 그렇지 않은지를 알아내는 방법왜 ? delete this 를 하고 싶은데 이게 heap 에 생성된 객체인지 아닌지를 모르니까 ..

하지만 그런 방법은 없다 !!

flag 를 만들어 new 할 때 true, delete 할 때 false 하는 방법 ? new [] 할 때 문제지역변수를 만들고 객체와 주소를 비교하면 ? data 영역에 저장될 경우 문제+ heap, stack 영역의 주소가 시스템마다 다르므로 이식성 떨어짐

이 객체가 어느 영역에 생성되었는지를 아는 것보다 포인터가 삭제해도 되는 것인지 판단이 더 쉬움주소 콜렉션을 생성한다 !!

주소 콜렉트를 하는 mixin 추상클래스를 만들고 ( 딱히 지정할 순수 가상 함수가 없을 땐 소멸자를 !!)

이놈을 상속받아서 사용하자 .

* mixin 클래스 : 명확한 기능 하나만을 제공하는 클래스 , 파생클래스의 다른 기능과 호환되도록 만듦

Page 7: 모어 이펙티브 c++ 5장 스터디

힙에만 생성되거나 힙에는 만들어지지 않는 클래스

객체가 힙에 생성되지 않게 하기간단하다 !!

operator new, delete, new[], delete[] 를 private 으로 만들자

파생 클래스에서는 ? public 으로 재 정의하지 않는 한 자연스럽게 해결된다 .

다른 클래스의 멤버로 쓰일 때 어떤 클래스가 new 한다 해도 그 멤버들까지 new 하는 건 아니다 .

문제 X

Page 8: 모어 이펙티브 c++ 5장 스터디

스마트 포인터리소스 관리 , 반복 코딩의 자동화 !! But 동작은 벙어리 포인터처럼 하자

생성 대입 소멸• 생성시 가리키는 대상은 nullptr 로 하자 .

• auto_ptr 은 복사 시 소유권이 이전된다 . 따라서 스마트포인터를 인자로 넘길 때 값복사 하지 말자 .

역참조 연산자 구현• operator* 로 실제 가리키는 포인터를 반환하자• operator-> 도 마찬가지로 pointee 를 가져오게 하자 .( 근데 std::shared_ptr 에서는 get

하던데 ..)

스마트 포인터가 nullptr 인지 점검• operator! 을 오버로딩해서 if (!ptn) 식으로 ..

• if(!pa == !po) 같은 구문은 대응 못함

Page 9: 모어 이펙티브 c++ 5장 스터디

스마트 포인터

스마트 포인터를 벙어리 포인터로 변환• 무슨 일이 있어도 operator() ( 암시적 변환 ) 를 지원하지 말자 – 지 멋대로 동작한다 .

스마트 포인터와 상속 기반의 타입변환• 스마트 포인터 객체는 설령 pointee 들끼리 상속관계에 있다 해도 그 관계를 알 방법이 없다 .

이 때는 암시적 변환 연산자를 위한 템플릿 함수 ( 멤버 함수 템플릿 ) 를 제공한다 . 클래스 내부에서template<class newType>

operator SmartPtr<newType>() { return SmartPtr<newType>(pointee); }

• 함수에서 부모 클래스의 smart pointer 를 인자로 받도록 정의되어 있을 때 , 자식 클래스의 객체를 인자로 넘기면 컴파일러 내부에서는1. 우선 부모 SP 클래스에서 자식클래스 SP 포인터를 취하는 ‘단일 인자 생성자’를 찾는다 .

2. 자식 SP 클래스에서 부모 SP 클래스로의 ‘암시적 타입 연산자’를 찾는다 .

3. 2 와 같은 일을 하는 ‘멤버 함수 템플릿’을 찾는다 .

Page 10: 모어 이펙티브 c++ 5장 스터디

스마트 포인터

스마트 포인터를 벙어리 포인터로 변환• 무슨 일이 있어도 operator() ( 암시적 변환 ) 를 지원하지 말자 – 지 멋대로 동작한다 .

스마트 포인터와 상속 기반의 타입변환• 스마트 포인터 객체는 설령 pointee 들끼리 상속관계에 있다 해도 그 관계를 알 방법이 없다 .

이 때는 암시적 변환 연산자를 위한 템플릿 함수 ( 멤버 함수 템플릿 ) 를 제공한다 . 클래스 내부에서template<class newType>

operator SmartPtr<newType>() { return SmartPtr<newType>(pointee); }

• 함수에서 부모 클래스의 smart pointer 를 인자로 받도록 정의되어 있을 때 , 자식 클래스의 객체를 인자로 넘기면 컴파일러 내부에서는1. 우선 부모 SP 클래스에서 자식클래스 SP 포인터를 취하는 ‘단일 인자 생성자’를 찾는다 .

2. 자식 SP 클래스에서 부모 SP 클래스로의 ‘암시적 타입 연산자’를 찾는다 .

3. 2 와 같은 일을 하는 ‘멤버 함수 템플릿’을 찾는다 .

우리는 그냥 .. std::shared_ptr 을 갖다 쓰자 !!