Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
Effective C++_3
131043 양현찬
NHN NEXT
생성자를 가상함수로 만들기
• 런타임에 입력 값에 따라 다른 타입의 객체를 생성해야 할 때
가상생성자가 매우 유용하다
가상 복사 생성자
• 가장 많이 사용되는 가상 생성자이다.
• 호출한 객체를 그대로 본따는 사본의 포인터를 반환한다.
• 기본 클래스의 가상 함수를 자식에서 재정의 해도 반환형은 다
르게 해도 된다.
클론을 사용하면 일반 복사 생성자도 쉽게 구현 가능하다.
비멤버 함수를 가상함수로 만들기
• 간단하다. 가상함수를 만들고 비멤버 함수 안에서 호출해버리자.
객체를 생성하지 않거나 1개만 생성하도록 제한
• 객체 생성을 막고 싶으면 생성자를 private으로 선언하자.
• 1개만 생성하도록 제한하고 싶다면..
• 우리는 이미 많이 사용하고 있다.
• 바로 ‘싱글톤’패턴이다. 생성자만 private으로 선언하면 완벽하
게 하나만 생성된다.
• 따로 전역함수로 빼서(보기 싫다면 namespace로 묶어주자) 함
수의 정적 객체로 만들어주면 함수가 생성될 때만 객체가 생성
된다.(싱글톤패턴에서는 포인터를 생성해서 반환하기 때문에 우
리가 해제 해줘야한다는 불편함이 있다.)
• 클래스에서 선언한 정적 객체는 그 초기화 시점이 정확하게 정
의 되어 있지 않다. (우리가 사용하는 싱글톤은 힙에 할당한다.)
프로젝트에 사용된 싱글톤 패턴의 input manager
정적 객체의 초기화 시점
• 함수의 정적 객체는 함수의 호출 시 초기화 된다.
• 클래스의 정적 객체의 경우 파일마다 뿔뿔히 흩어져 있을 경우 알아
낼 수가 없다.
• 실제로 이러한 성질 때문에 많은 문제들이 발생하기 때문에 주의해
야 한다.
• 비멤버 함수에 있어서 inline은 이 함수는 internal linkage(내부연결)
을 가진다는 뜻이다.
• Internal linkage는 목적 코드 안에서 두 개 이상 나타날 수 있다.
• 절대 정적 객체가 있는 비멤버 함수에서는 inline을 선언해서는 안된
다.
• 객체의 생성숫자를 여러 개로 제한하고 싶다면 전역변수 쓰자.
객체 생성이 이루어지는 세 가지 상황
• 1.그 자체로 생성될 때.
• 2.파생된 객체의 기본 클래스 부분으로 만들어 질 때.
• 3.다른 객체의 클래서 멤버로 만들어 질 때.
• 객체를 상속은 불가능하게, 생성은 가능하게 하고 싶을 때.
이 방법에 전역 변수까지 사용하면 한번에
생성되는 인스턴스의 개수를 제한할 수 있다.
인스턴트 카운팅 기능을 가진 기본 클래스
이 클래스를 상속받아서 사용할 수 있다.
Public으로 해도 문제 없지만 Counted클래스를 가상 소멸자로 해주어야 한다.
힙에만 생성되도록 디자인 하고 싶을 때
• 소멸자를 private으로 선언하면 힙에만 생성할 수 있도록 제한
할 수 있다.
• 상속은 가능하도록 하고 싶다면 protected로 선언하자.
• 다른 객체에서 소유하도록 하고 싶다면 포인터를 물고 있도록
하자.
• 반대로 힙에 생성되지 않도록 하고 싶다면 operator new와
delete 연산자를 private으로 선언하자.
힙에 생성되었는지 확인하는 방법
• Mix in클래스는 명확한 기능 하나만 제공하는 클래스로 파생 클
래스가 제공하는 다른 기능과 호환되도록 설계된 클래스이다.
힙에 생성을 확인할 수 있는 mix in클래스
스마트 포인터
• 생성과 소멸 타이밍을 조절할 수 있다.
• 복사와 대입 연산자를 조절 할 수 있다.
• 역참조 동작을 조절 할 수 있다.
• 스마트 포인터가 복사되거나 대입될 때 하는 행동을 주시하자
• 스마트 포인터는 *,->연산자들을 통해 역참조가 가능하다.
• Operator *, operator->연산자들을 사용하여 역참조 할 수 있도
록 설계되어있다.
• 스마트 포인터의 null값 확인은 직관적으로 가능하다.
• Operator void* 연산자를 통해 널이면 0을 반환하도록 한다.
스마트 포인터를 일반 포인터로 변환하기
• 스마트 포인터를 잘 모르는 친구가 &*ptr이런 형식으로 일반 포
인터로 변환하는 것을 보며 충격에 빠졌던 경험이 있다.
• 많은 api들이 일반 포인터를 인자로 받도록 설계되어있다.
• Auto_ptr에서는 get()함수를 제공하고 있다.
• 스마트 포인터를 일반 포인터로 변환하는 암시적 타입 연산자
를 제공하면 버그를 유발할 수 있다.
스마트 포인터와 상속 기반의 타입변환
• 컴파일러는 사용자 정의 타입변환을 한번에 두 번 이상 할 수
없다.
• 아래 방법을 이용하면 일반 포인터의 암시적 타입변환을 흉내
낼 수 있다.
스마트 포인터와 const
• 일반 포인터의 const는 포인터가 가르키는 것과 포인터 그 자체
를 상수로 만들 수 있었다.
• 비상수를 상수로 만드는 것은 안전하지만 상수를 비상수로 만
드는 것은 매우 위험하다.
• 이러한 성질은 상속관계인 is - a와 비슷하다.
• 이를 이용하여 상수용 스마트 포인터를 만들어준다.
More effective c++ 3
참조 카운팅
• Shared_ptr을 생각해보자. 참조 횟수만 가지고 있고 참조하는
포인터는 모두 동일하다.
• 대입 연산자가 호출될 때 참조 횟수는 증가하여야 한다.
• 참조 횟수가 0가 될 때에 그 값을 해제한다.
• 참조 카운팅을 하는 만큼 비용이 따른다. 따라서 필요한 상황에
맞게 사용되어야 한다.
• 필요한 상황을 판별하는 경우는 직관에 따르면 안되고 프로파
일러를 통해 객관적으로 판단되어야 한다.

More Related Content

More effective c++ 3

  • 2. 생성자를 가상함수로 만들기 • 런타임에 입력 값에 따라 다른 타입의 객체를 생성해야 할 때 가상생성자가 매우 유용하다
  • 3. 가상 복사 생성자 • 가장 많이 사용되는 가상 생성자이다. • 호출한 객체를 그대로 본따는 사본의 포인터를 반환한다. • 기본 클래스의 가상 함수를 자식에서 재정의 해도 반환형은 다 르게 해도 된다.
  • 4. 클론을 사용하면 일반 복사 생성자도 쉽게 구현 가능하다.
  • 5. 비멤버 함수를 가상함수로 만들기 • 간단하다. 가상함수를 만들고 비멤버 함수 안에서 호출해버리자.
  • 6. 객체를 생성하지 않거나 1개만 생성하도록 제한 • 객체 생성을 막고 싶으면 생성자를 private으로 선언하자. • 1개만 생성하도록 제한하고 싶다면.. • 우리는 이미 많이 사용하고 있다. • 바로 ‘싱글톤’패턴이다. 생성자만 private으로 선언하면 완벽하 게 하나만 생성된다. • 따로 전역함수로 빼서(보기 싫다면 namespace로 묶어주자) 함 수의 정적 객체로 만들어주면 함수가 생성될 때만 객체가 생성 된다.(싱글톤패턴에서는 포인터를 생성해서 반환하기 때문에 우 리가 해제 해줘야한다는 불편함이 있다.) • 클래스에서 선언한 정적 객체는 그 초기화 시점이 정확하게 정 의 되어 있지 않다. (우리가 사용하는 싱글톤은 힙에 할당한다.)
  • 7. 프로젝트에 사용된 싱글톤 패턴의 input manager
  • 8. 정적 객체의 초기화 시점 • 함수의 정적 객체는 함수의 호출 시 초기화 된다. • 클래스의 정적 객체의 경우 파일마다 뿔뿔히 흩어져 있을 경우 알아 낼 수가 없다. • 실제로 이러한 성질 때문에 많은 문제들이 발생하기 때문에 주의해 야 한다. • 비멤버 함수에 있어서 inline은 이 함수는 internal linkage(내부연결) 을 가진다는 뜻이다. • Internal linkage는 목적 코드 안에서 두 개 이상 나타날 수 있다. • 절대 정적 객체가 있는 비멤버 함수에서는 inline을 선언해서는 안된 다. • 객체의 생성숫자를 여러 개로 제한하고 싶다면 전역변수 쓰자.
  • 9. 객체 생성이 이루어지는 세 가지 상황 • 1.그 자체로 생성될 때. • 2.파생된 객체의 기본 클래스 부분으로 만들어 질 때. • 3.다른 객체의 클래서 멤버로 만들어 질 때. • 객체를 상속은 불가능하게, 생성은 가능하게 하고 싶을 때. 이 방법에 전역 변수까지 사용하면 한번에 생성되는 인스턴스의 개수를 제한할 수 있다.
  • 10. 인스턴트 카운팅 기능을 가진 기본 클래스 이 클래스를 상속받아서 사용할 수 있다.
  • 11. Public으로 해도 문제 없지만 Counted클래스를 가상 소멸자로 해주어야 한다.
  • 12. 힙에만 생성되도록 디자인 하고 싶을 때 • 소멸자를 private으로 선언하면 힙에만 생성할 수 있도록 제한 할 수 있다. • 상속은 가능하도록 하고 싶다면 protected로 선언하자. • 다른 객체에서 소유하도록 하고 싶다면 포인터를 물고 있도록 하자. • 반대로 힙에 생성되지 않도록 하고 싶다면 operator new와 delete 연산자를 private으로 선언하자.
  • 13. 힙에 생성되었는지 확인하는 방법 • Mix in클래스는 명확한 기능 하나만 제공하는 클래스로 파생 클 래스가 제공하는 다른 기능과 호환되도록 설계된 클래스이다. 힙에 생성을 확인할 수 있는 mix in클래스
  • 14. 스마트 포인터 • 생성과 소멸 타이밍을 조절할 수 있다. • 복사와 대입 연산자를 조절 할 수 있다. • 역참조 동작을 조절 할 수 있다. • 스마트 포인터가 복사되거나 대입될 때 하는 행동을 주시하자 • 스마트 포인터는 *,->연산자들을 통해 역참조가 가능하다. • Operator *, operator->연산자들을 사용하여 역참조 할 수 있도 록 설계되어있다. • 스마트 포인터의 null값 확인은 직관적으로 가능하다. • Operator void* 연산자를 통해 널이면 0을 반환하도록 한다.
  • 15. 스마트 포인터를 일반 포인터로 변환하기 • 스마트 포인터를 잘 모르는 친구가 &*ptr이런 형식으로 일반 포 인터로 변환하는 것을 보며 충격에 빠졌던 경험이 있다. • 많은 api들이 일반 포인터를 인자로 받도록 설계되어있다. • Auto_ptr에서는 get()함수를 제공하고 있다. • 스마트 포인터를 일반 포인터로 변환하는 암시적 타입 연산자 를 제공하면 버그를 유발할 수 있다.
  • 16. 스마트 포인터와 상속 기반의 타입변환 • 컴파일러는 사용자 정의 타입변환을 한번에 두 번 이상 할 수 없다. • 아래 방법을 이용하면 일반 포인터의 암시적 타입변환을 흉내 낼 수 있다.
  • 17. 스마트 포인터와 const • 일반 포인터의 const는 포인터가 가르키는 것과 포인터 그 자체 를 상수로 만들 수 있었다. • 비상수를 상수로 만드는 것은 안전하지만 상수를 비상수로 만 드는 것은 매우 위험하다. • 이러한 성질은 상속관계인 is - a와 비슷하다. • 이를 이용하여 상수용 스마트 포인터를 만들어준다.
  • 19. 참조 카운팅 • Shared_ptr을 생각해보자. 참조 횟수만 가지고 있고 참조하는 포인터는 모두 동일하다. • 대입 연산자가 호출될 때 참조 횟수는 증가하여야 한다. • 참조 횟수가 0가 될 때에 그 값을 해제한다. • 참조 카운팅을 하는 만큼 비용이 따른다. 따라서 필요한 상황에 맞게 사용되어야 한다. • 필요한 상황을 판별하는 경우는 직관에 따르면 안되고 프로파 일러를 통해 객관적으로 판단되어야 한다.