[ Effective C++ ] 항목 28 : 내부에서 사용하는 객체에 대한 '핸들' 을 반환하는 코드는 되도록 피하자

Minsu._.Lighting·2023년 12월 5일
0

[ 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를 붙였든...
- 함수의 반환값이 상수든 아니든...

  • 핸들을 반환하는 함수라는 이유 하나로 무효참조 핸들은 발생할 수 있다!

📢 핸들을 반환하는 멤버 함수를 '절대로' 만들지 말라는 이야기가 아니다!

  • operator[] 연산자와 같이 내부적으로 참조자를 반환하는 동작을 하는 함수도 제공 되기도 한다!
    - 하지만 이런 함수는 예외적 이므로 되도록 핸들 반환은 피하자!
profile
오코완~😤😤

0개의 댓글

관련 채용 정보