서적/Effective C++
항목 51: new 및 delete를 작성할 때 따라야 할 기존의 관례를 잘 알아 두자
기존의 관례에 잘 맞는 operator new를 구현하려면 다음의 요구사항만큼은 기본으로 지켜야 합니다. - 반환 값이 제대로 되어 있어야 합니다. - 가용 메모리가 부족할 경우에는 new 처리자 함수를 호출(항목 49) - 크기가 없는 (0byte) 메모리 요청에 대한 대비책 - 기본 형태의 new가 가려지지 않도록 해야합니다. void* operator new(std::size_t size) throw(std::bad_alloc) { using namespace std; if(size == 0) { size = 1; } while (true) { //size 바이트를 할당 if(/*할당 성공*/) { return (/*할당된 메모리에 대한 포인터*/); } //할당 실패 시, 현재 new 처리자 함수..
항목 49: new 처리자의 동작 원리를 제대로 이해하자
operatore new 함수는 예외를 던지게 되어 잇습니다. 메모리 할당이 제대로 되지 못한 상황에 대한 반응으로 operator new가 예외를 던지기 전에, 이 함수는 사용자 쪽에서 지정할 수 있는 에러 처리 함수를 우선적으로 호출하도록 되어 있는데, 이 에러 처리 함수를 가리켜 new 처리자라고 합니다. set_new_handler는 new_handler를 받고 new_handler를 반환하는 함수입니다. 즉, set_new_handler가 받아들이는 new_handler 타입의 매개변수는 요구된 메모리를 operator new가 할당하지 못했을 때 operator new가 호출할 함수의 포인터입니다. new 처리자 함수가 다음 동작 중 하나를 꼭 해주어야함. - 사용할 수 있는 메모리를 더 많이..
항목 36: 상속 받은 비가상 함수를 파생 클래스에서 재정의하는 것은 금물!
- 비가상함수는 정적 바인딩 - 가상함수는 동적 바인딩 - 상속받은 비가상 함수를 재정의하는 일은 절대로 하지 맙시다.
항목 35: 가상함수 대신 쓸 것들도 생각해 두는 자세를 시시때때로 길러 두자
- 비가상 인터페이스 관용구를 통한 템플릿 메서드 패턴 - 가상 함수는 반드시 private 멤버로 두어야한다. - 사용자로 하여금 public 비가상 멤버 함수를 통해 private 가상 함수를 간접적으로 호출하게 만드는 방법 - 함수 포인터로 구현한 전략 패턴 - std::function - 고전적인 전략 패턴 - 한 쪽 클래스 계통에 속해 있는 가상 함수를 다른 쪽 계통에 있는 가상 함수로 대체
항목 34: 인터페이스 상속과 구현 상속의 차이를 제대로 파악하고 구별하자
- 순수가상함수를 선언하는 목적은 파생 클래스에게 함수의 "인터페이스"만을 물려주려는 것 - 단순 가상함수를 선언하는 목적은 파생 클래스로 하여금 함수 인터페이스뿐만 아니라 그 함수의 기본 구현도 물려받게 하자는 것 - 비가상함수를 선언하는 목적은 파생클래스가 함수 인터페이스와 더불어 그 함수의 필수적인 구현을 물려 받게 하는 것 - 결정적인 실수 두 가지를 피하자 - 모든 멤버 함수를 비가상함수로 선언하는 것을 피하자 - 모든 멤버함수를 가상함수로 선언하는 것을 피하자 - 인터페이스 상속은 구현 상속과 다릅니다. public 상속에서, 파생 클래스는 항상 기본 클래스의 인터페이스를 모두 물려 받습니다.
항목 33: 상속된 이름을 숨기는 일은 피하자
- 어떤 기본 클래스로부터 상속을 받으려고 하는데, 오버로드된 함수가 그 클래스에 들어있고 이 함수들 중 몇 개만 재정의하고 싶다면, 각 이름에 대해 using 선언을 붙여주어야한다. - 파생클래스의 이름은 기본클래스의 이름을 가립니다. - 파생 클래스의 이름은 기본 클래스의 이름을 가립니다. public 상속에서는 이런 이름 가림 현상은 바람직하지 않습니다. - 가려진 이름을 다시 볼 수 있게 하는 방법으로, using 선언 혹은 전달 함수를 쓸 수 있습니다.
항목 32: Public 상속 모형은 반드시 "is-a"를 따르도록 만들자
- 유효하지 않은 코드를 컴파일 단계에서 막아주는 인터페이스가 좋은 인터페이스 - 클래스들 사이에 맺을 수 있는 관계로 "is-a", "has-a", "is-implemented-in-terms-of" - public 상속의 의미는 is-a입니다. 기본 클래스에 적용되는 모든 것들이 파생 클래스에 그대로 적용되어야 합니다. 왜냐하면 모든 파생 클래스 객체는 기본 클래스 객체의 일종이기 때문입니다.
항목 2: #define을 쓰려거든 const, enum, inline을 떠올리자
"가급적 전처리기보다 컴파일러를 더 가까이 하자" #define ASPECT_RATIO 1.653 이런 경우 숫자 상수로 대체된 코드에서 컴파일 에러라도 발생하게 되면 꽤나 헷갈릴 수 있습니다. 소스 코드엔 분명히 ASPECT_RATIO가 있었는데 에러 메시지엔 1.653으로 나오기 때문에 헷갈릴 수 있습니다. const double AspectRatio = 1.653; 매크로를 쓰면 코드에 ASPECT_RATIO가 등장하기만 하면 전처리기에 의해 1.653으로 모두바뀌면서 결국 Object Code 에서 1.653의 사본이 등장 횟수만큼 들어가게 되지만, 상수 타입의 AspectRatio는 아무리 여러 번 쓰이더라도 사본은 딱 한 개만 생기기 떄문입니다. 여기까지 정리하자면, 해당 매크로가 많이 사용된..
항목 1: C++를 언어들의 연합체로 바라보는 안목은 필수
오늘날의 C++는 다중 패러다임 프로그래밍 언어라고 불립니다. C C++는 여전히 C를 기본으로 하고 있습니다. 블록, 문장, 선행 처리자, 기본 제공 데이터 타입, 배열, 포인터 등 모든 것이 C에서 왔습니다. 객체 지향 개념의 C++ 클래스를 쓰는 C 클래스, 캡슐화 상속, 다형성, 가상 함수 등 템플릿 C++ 템플릿 메타프로그래밍 STL 네 가지의 하위 언어들이 C++를 이루고 있습니다.