C++/More Effective C++

[More Effective C++] Chap1. 기본 개념들

라부송 2020. 2. 5. 19:42

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) 템플릿 기반의 컨테이너 클래스의 적용할 수 없다

 

그럼 기본 생성자를 왜 없애느냐?

내용물이 없으면 쓸모가 없는 클래스에서 실제로 내용물이 들어있는지 검사하는 코드를 항상 가져야 하기 때문

이걸로 인한 낭비가 꽤 심하니 쓸데 없는 상황에선 복잡해지더라도 기본 생성자를 피하는게 더 효율적이다