[More Effective C++] Chap1. 기본 개념들
1. 포인터와 참조자를 구별하자
포인터는 null 가리키는게 되는데 참조자는 안 됨. 무조건 객체를 가리켜야 한다
포인터 - 다른 객체 참조할 수 있음
참조자 - 초기화할 때 참조했던 그 객체만 참조 가능
operator[] 을 사용해야 할 때 참조자로 반환하도록 하는게 보통
2. 가능한 C++ 스타일의 캐스트를 즐겨 쓰자
캐스트는 형변환이라는 뜻
C스타일 캐스트의 문제점
- 아무 생각이 없다
- 눈으로 찾아내기가 힘들다 .. 소스코드 안에서 괄호 쓰는게 한두개가 아니기 때문
아래는 cast 연산자 예시 중 하나고
C언어 : double result = ((double) firstNumber) / secondNumber
C++ : double result = static_cast<double> (firstNumber) / secondNumber
위와 같이 바뀜으로써 인간의 눈으로 발견하기 쉬운 캐스트가 됨
1. static_cast
- C 스타일 캐스트와 똑같은 능력임. 기본적 연산자 (표현식의 상수성은 떼지 못함)
2 const_cast
- 상수성 혹은 휘발성 제거 용도
const_cast<SpecialWidget*>(&csw)
3. dynamic_cast
- 상속 관계를 가로지를 때 안전하게 캐스팅하기 위해 사용됨
- 업캐스팅을 위한 것
- 가상 함수가 없는 타입엔 사용 불가
4. reinterpret_cast
- 함수 포인터 타입을 서로 바꿀 때 많이 쓰임
- 컴파일러마다 변환 결과가 다르게 정의되기 때문에 이식성이 없다 최대한 피해야함
3. 배열과 다형성은 동반자가 아니다
- 기본 클래스를 통해 파생 클래스 객체를 조작할 수 있다는걸 다형성이라 칭하고, 배열도 이에 포함된다.
- 그러나 배열은 다형성과 크게 잘 섞이지 않는다
ex1 ) 기본 클래스 타입 배열 매개변수로 파생 클래스 배열을 전달할 때 (객체 크기가 달라서 컴파일은 될지언정 제대로 동작하지 않음)
ex2 ) 기본 클래스로 파생 클래스 배열의 소멸자를 호출하려 할 때
4. 쓸데 없는 기본 생성자는 그냥 두지 말자
기본 생성자가 없는 클래스의 문제점
1) 기본 생성자 없는 클래스는 배열 만들고 소멸시키기가 너무 복잡하다
class EquipmentPiece {
public:
EquipmentPiece(int number);
...
};
EquipmentPiece bestpieces[10]; // 기본 생성자가 없기 때문에 에러
/* Solution */
int ID1, ID2, ID3....
EquipmentPiece bestpieces[10] = {
EquipmentPiece(ID1),
EquipmentPiece(ID2),
....
} // 에러 안 남
2) 템플릿 기반의 컨테이너 클래스의 적용할 수 없다
그럼 기본 생성자를 왜 없애느냐?
내용물이 없으면 쓸모가 없는 클래스에서 실제로 내용물이 들어있는지 검사하는 코드를 항상 가져야 하기 때문
이걸로 인한 낭비가 꽤 심하니 쓸데 없는 상황에선 복잡해지더라도 기본 생성자를 피하는게 더 효율적이다