Const를 통해 수정을금지하고 있다.
여전히 무효참조 핸들에 대한 위험을 안고 있다.
만약 pData가 메모리에서 해제되어버리게 된다면?
반환된 const Point& 값을 가지고 있는 변수가 있다면
내용이 사라진 주소 값만 물고 있다.
되도록이면 최대한 피하자! 값만 제공하는 용도라면 사본을 반환할 수도 있다.
정리
• 포인터로 충분한경우 객체를 직접 사용하지 말자
• 클래스 정의 대신 선언에 최대한 의존하도록 하자
• 클래스를 쪼갤 경우(pimpl) 선언과 정의에 대해 각각의 헤더파
일을 제공하자
• 템플릿 선언과 정의를 분리할 수 있도록 하는 기능을 export라
는 키워드로 제공하고 있다.(아직은 쓰기에는 시기상조)
캐릭터의 체력계산은 캐릭터마다다르게 계산해야 한다.
너무 당연한 설계다. 하지만 다른 방법이 없을까?
당연한 설계를 두고 다른 방법을 염두에 두는 것은 너무 어려운 일이다.
76.
가상함수 은폐론
가상함수는 private으로선언
가상함수를 사용할 수 있는 인터페이스를 제공한다.
비 가상함수 인터페이스라 한다.
혹은 wrapper라고 한다.
하지만 엄격하게 private으로 선언될 필요는 없다. 상속받는 클래스에서
이 부분의 사용을 염두에 두고 protected로 선언 할 수 있다.
이 부분을 강조해서봅시다.
Tr1::function타입
이걸로 만들어진 객체는 앞으로 대상 시그니처(<>속의 타
입)와 호환되는 함수호출성 개체를 어떤 것도 가질 수 있다.
여기서 호환된다는 뜻은 ‘암시적 변환이 가능하다'라는 뜻이다.
말로는 어려우니 사용방법을 봅시다.
왜 복잡하게 두가지 의미인가?
• 응용 영역
• 구현 영역
캐릭터, hp, 몬스터 등의 의미를 가진 객체
객체는 두 가지 영역이 있기 때문이다.
버퍼, 뮤텍스, 탐색트리 등의 시스템구현을 위한 인공물
응용 – has-a
구현 – Is implemented in terms of
97.
돌아가서 객체의 합성을이용하자
Set이라는 자료구조를 list에서부터 다시 만들고 싶다.
하지만 list는 중복을 허용하고 Set은 중복을 허용하지 않으니 is-a관계는 부적절하다.
이럴 때는 list를 사용해서 구현되는 (Is implemented in terms of) 형태를 사용하자
Private상속
• 컴파일러가 파생클래스를 기본 클래스로 변환하지 않는다.
• 기본 클래스에서 물려받은 멤버는 모조리 private멤버가 된다.
• Is-implemented-in-terms-of라는 의미를 가진다.
• 즉 파생 클래스와 기본 클래스간의 어떠한 의미 없는 그냥 구현
기법 중 하나다.
101.
잠깐 합성하고 차이가뭐야?
• 그냥 합성을 써라
• Private을 꼭 사용해야 할 경우만 써라
• 비공개 멤버에 접근하고 싶거나
• 가상함수를 재정의 하고 싶거나
• 어쩔 수 없이 private을 사용해야만 하거나
기본적으로는 중복 생성한다.
하지만하나만 존재하도록 만들 수 있다.
가상 상속을 사용해야 한다.
재미있는 점은 표준 C++라이브러리가 이 형태를 가지고 있다.
basic_iostream이 이 형태로 이루어져 있다.
생각해보면 모든 public상속이 전부 virtual이 붙어야 한다.
하지만 virtual을 붙였을 때 드는 비용을 생각하자
110.
가상상속의 비용들
• 컴파일러의숨겨진 비용뿐만 아니라 우리의 뇌 자원도 빼앗아
간다.
• 초기화가 필요한 가상 기본 클래스에서 파생된 경우
• 기존의 클래스 계통에 새로 파생 클래스를 추가할 경우
• 전부 고려해야 한다
• 그냥 쓰지 말자
• 꼭 써야 한다면, 가상 기본 클래스의 내용을 최대한 줄이자.
111.
그래도 쓸만할 때가있다
한쪽은 public, 다른 한쪽은 private으로 상속받고 있다.
이 형태를 기억해두자.