[ Effective C++ ] 정리 모음집
" C++ 프로그래머의 필독서, 스콧 마이어스의 Effective C++ 를 읽고 내용 요약 / 정리 "
" 객체 내부에 대한 핸들을 반환하는 함수는 어떻게든 위험하다! "
- 어떤 객체의 내부요소에 대한 핸들(참조자, 포인터, 반복자)을 반환하는 것은 되도록 피하자, 캡슐화 정도를 높이고, 상수 멤버 함수가 객체의 상수성을 유지한 채로 동작할 수 있도록 하며, 무효참조 핸들이 생기는 경우를 최소화할 수 있다.
class Point
{
public:
Point(int x, int y);
...
void setX(int newVal);
void setY(int newVal);
...
};
struct RectData
{
Point ulhc; // 좌측 상단 (uppter left-hand corner)
Point ulhc; // 우측 하단 (lower right-hand corner)
};
class Rectangle
{
publc:
...
Point& upperLeft() const { return pData->ulhc; }
Point& lowerRight() const { return pData->lrhc; }
...
private:
shared_ptr<RectData> pData;
상수 멤버 함수인 upperLeft, lowerRight 함수의 반환값이 private 내부 데이터 참조자 이다.
- 꼭짓점 정보만 사용자에게 제공하고 객체를 수정하는 일이 없도록 설계 했으나, 반환값 참조자를 통해 내부 데이터가 수정될 수 있는 문제 발생
클래스 데이터 멤버는 아무리 숨겨봤자 그 멤버의 참조자를 반환하는 함수들의 최대 접근도에 따라 캡슐화 정도가 정해짐
- private 멤버여도 해당 데이터의 참조자를 반환하는 함수가 public이면 실질적으로 public 멤버인 셈
📢 참조자 뿐만 아니라 포인터, 반복자 또한 마찬가지!
- 참조자, 포인터, 반복자는 모두 다른 객체에 손을 댈 수 있게 하는 매개자
- 핸들을 반환하게 만들면 언제든지 객체의 캡슐화를 무너뜨리는 위험을 무릅써야 함
반환 타입에 const 키워드를 붙여 객체의 상태를 바꾸지 못하도록 하자
- 컴파일러 수준에서 막음
의도적인 캡슐화 완화
- 사용자들이 Rectangle을 구성하는 Point를 들여다 보게 처음부터 설계 했기 때문
📢 무효참조 핸들 발생 위험!
class GUIObject { ... };
const Rectangle boundingBox(const GUIObject* obj);
...
GUIObject *pgo;
...
const Point *pUpperLeft = &(boudingBox(*pgo).upperLeft());
- 포인터이든, 참조자이든, 반복자이든...
- 핸들에 const를 붙였든...
- 함수의 반환값이 상수든 아니든...
📢 핸들을 반환하는 멤버 함수를 '절대로' 만들지 말라는 이야기가 아니다!