MoreEffectiveC++_Chapter01

2016. 6. 6. 02:59책/책 공부

 

 

 

 

 


 

<item1> 포인터(pointer) 와 참조자(reference)를 구분하자

 

reference 는 다음 3가지일 경우에 사용한다

1. 참조하고자 하는 객체를 미리 알고 있을 때     (선언과 동시에 초기화가 될 때)

2. 다른 객체로 바꾸어 참조할 일이 결코 없을 때 (상수성)

3. 포인터를 사용하면 문법상 의미가 어색해지는 연산자를 오버라이딩 할 때 (operator[] 같은)

 

위 3가지 경우를 제외하곤 모두 포인터를 사용한다

 


 

<item2> 가능한 C++ 스타일 캐스트를 쓰자

 

이유?

    가독성과 의미전달이 확실하기 때문에 C++ 스타일 캐스팅을 사용하는 것이 좋다

 

-static_cast        : 일반적인 타입변환

-const_cast        : const 또는 volatile 속성을 제거

-dynamic_cast    : derived 또는 sibling 클래스 타입으로 변환, 단, 가상함수가 있어야 한다

-reinterpret_cast : 컴파일러에 따라 다르게 정의되어 있다 (이식성 제로)

                        주로 함수포인터 타입변환이 필요할 때 쓰인다. 안 쓰는게 좋다

 


 

 

<item3> 배열과 다형성은 같은 수준으로 놓고 볼 것이 아니다

 

 

부모클래스 타입의 배열포인터를 받는 함수에, 자식클래스 타입의 배열을 넘겨줄 경우

배열의 요소들을 접근할 때 포인터연산을 하는데, 이 때 문제가 발생한다

 

자식클래스의 크기만큼 포인터연산이 이루어져야하는데, 함수의 파라미터는 부모클래스 타입의 배열이므로

부모클래스의 크기만큼 포인터연산이 발생한다 -> 미정의 작동을 하게된다

 

1.  array[3] 같은 구문 (배열의 [] 연산자는 포인터연산이 들어간다 a[3] -> *(a+sizeof(classA)*3)

2.  delete [] array;

    각 요소들 마다 소멸자를 호출해준다. 결국 [] 연산자가 내부적으로 돈다

 

 

배열과 다형성은 물과 기름

 


 

<item4> 쓸 데없는 기본생성자를 그냥 두지 말자

 

무조건 파라미터로 멤버변수가 초기화되야 하는 클래스 객체일 경우, 기본 생성자가 있어서는 안된다

 

쓸 데없는 기본 생성자가 있으면, 멤버변수가 초기화되지 않는 문제 발생 소지가 있다

 

기본 생성자가 없을 경우 생기는 문제점

- Foo *pf = new Foo() 같이 인스턴스 생성 불가능

- 템플릿 설계의 컨테이너들을 사용하기 어려워진다

 

기본 생성자가 없어야 함에도 만들어둘 경우 생기는 문제점

- 멤버함수마다 멤버변수들이 초기화되지 않았을 경우를 검사하기 위해 Valid 체크 로직을 추가해야한다

 

위 두 가지 경우를 저울질 해서 기본생성자를 만들지 말지 결정하면 된다

 

꼼수

   포인터 배열을 만들고, 각 요소마다 동적할당을 해준다

   Foo** af = new Foo*[10];

   for( int i = 0 ; i < 10; i++ )

       af = new Foo(value);