일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- UE4
- 반복자
- 영화
- 암시적 변환
- exception
- 언리얼
- 예외
- implicit conversion
- 메타테이블
- 티스토리챌린지
- reference
- effective stl
- Vector
- 스마트 포인터
- virtual function
- Smart Pointer
- 상속
- 오블완
- 루아
- lua
- 게임
- more effective c++
- 참조자
- 영화 리뷰
- operator new
- 다형성
- Effective c++
- resource management class
- c++
- 비교 함수 객체
Archives
- Today
- Total
스토리텔링 개발자
[Effective C++] 28. 클래스 내부 private 객체에 대한 핸들 리턴 문제 본문
728x90
항목 28. 내부에서 사용하는 객체에 대한 ‘핸들’을 반환하는 코드는 되도록 피하자.
참조자 반환 함수에 대한 고찰
- 메모리 부담을 최대한 줄이기 위해 실 데이터를 가리키는 포인터를 가지고 있는 사각형 클래스를 만든다.
-
class Point { public: Point(int x, int y); ... void setX(int newVal); void setY(int newVal); ... }; class RectData { Point ulhc; // 좌측 상단 Point lrhc; // 우측 하단 }; class Rectangle { public: .... // 참조자 형태로 꼭지점 정보를 반환한다. Point& upperLeft() const { return pData->ulhc; } Point& lowerRight() const { return pData->lrhc; } .... private: shared_ptr<RectData> pData; // 꼭지점 정보를 가리킨다. }
- 여기서 upperLeft, lowerRight 함수가 값을 참조자 형태로 반환하는 것은 잘못이다.
- 상수 멤버 함수로 설정되어 있으나, 반환되는 참조자로 인해 외부에서 내부값을 마음대로 수정할 수 있다는 맹점이 있다.
- 즉, pData가 아무리 private로 선언되어 있더라도, 실질적으로는 public이나 다름 없다.
- 이는 비트 수준 상수성의 한계이다.
핸들
- 다른 객체가 손을 댈 수 있게 하는 매개자
- 참조자, 포인터, 반복자
- 핸들을 반환하게 하면 그 객체의 캡슐화를 무너뜨리는 위험을 무릅쓸 수밖에 없다.
어떤 객체의 내부 요소(internals)는 공개하지 말 것
- 내부 요소에는 데이터 멤버 뿐 아니라 일반적 수단으로 접근이 불가능한 멤버 함수도 포함된다.
- 즉, protected 또는 private 멤버 함수 역시 내부 요소이다.
- 따라서 외부 공개가 차단된 멤버 함수의 포인터를 반환하는 멤버 함수 역시 절대 만들면 안된다.
해결법
- 참조자를 사용하면서도 공개 수준을 지키는 방법은, const 참조자로 리턴하는 것이다.
-
const Point& upperLeft() const { return pData->ulhc; } const Point& lowerRight() const { return pData->lrhc; }
- 하지만 이 경우에도 무효 참조 핸들이 발생할 여지가 있으므로 위험 요소가 없는 것은 아니다.
무효 참조 핸들
- 핸들은 유효하지만, 핸들의 실제 객체 데이터가 사라진 경우.
-
class GUIObject { ... }; // Rectangle 객체를 값으로 반환한다. // const 가 붙는 이유는 항목 3 참조 const Rectangle boundingBox(const GUIObject& obj); ... GUIObject *pgo; ... const Point* pUpperLeft = &(boundingBox(*pgo).upperLeft()); // boundingBox가 만든 임시객체는 유효범위를 벗어나면 소멸된다. // 허나 pUpperLeft는 해당 임시객체의 내부 요소를 핸들로 가지고 있다.
- 일단 바깥으로 떨어져 나간 핸들은 그 핸들이 참조하는 객체보다 더 오래 살 위험이 있다는 점을 유의해야 한다.
728x90
'개발 > Effective C++' 카테고리의 다른 글
[Effective C++] 30. 인라인 함수 (0) | 2024.06.26 |
---|---|
[Effective C++] 29. 예외 안전성 (0) | 2024.06.25 |
[Effective C++] 27. 캐스팅 (0) | 2024.06.21 |
[Effective C++] 26. 필요한 시점 직전에 변수를 정의할 것 (0) | 2024.06.20 |
[Effective C++] 25. 예외를 던지지 않는 swap 함수 (0) | 2024.06.19 |
Comments