방프리
17.10.23. Effective C++ 5. 구현 (항목28) 본문
항목 28 : 내부에서 사용하는 객체에 대한 '핸들'을 반환하는 코드는 되도록 피하자
이 항목에 대해 알아보기 전 '핸들'에 대해 먼저 짚고 가는 것이 좋을 것 같습니다.
핸들이란? 다른 객체에 접근할 수 있게 해주는 매개자를 말합니다. 간단하게 get, set 함수를 예를 들 수 있겠네요
get, set 함수는 캡슐화의 규약을 지키면서 데이터를 조작, 접근을 가능하게 해줍니다.
하지만 get, set 함수를 가지고 있는 클래스를 멤버변수로 가지고 있는 클래스에서도 데이터 조작이 가능해집니다.
즉, 캡슐화를 위해 만든 함수가 다른 방법을 통해 조작이 이루어진다는거죠
private 또는 protected로 선언된 변수들은 보호받을 권리가 있습니다. 이들 변수 외에도
포인터와 같은 핸들을 반환하는 코드로 된 것은 많은 문제를 일으킬 확률이 높습니다.
그래서 const를 통해 핸들을 통해 읽어오는 매개자를 읽는 방식으로만 사용하도록 만듭니다.
물론 이 방식도 무효참조 핸들(dangling handle)의 문제를 안고 있습니다.
할당되지 않은 변수를 참조할 때 터지게 된다는 것이죠.
그래서 되도록이면 핸들을 반환하는 코드는 피하도록 해야합니다. 물론 사용해야하는 경우도 있습니다.
주된 예는 STL 컨테이너에서 찾을 수 있는데 operator[] 같은 연산자는 원소를 참조해야하기 때문에
사용될 수도 있습니다.
자주 사용되고 필요로 할 수도 있는 코드방식이기 때문에 이런 오류를 한번쯤 생각해볼만 한 것 같습니다.
이것만은 잊지말자!
* 어떤 객체의 내부요소에 대한 핸들(참조자, 포인터, 반복자)을 반환하는 것은 되도록 피하세요. 캡슐화 정도를
높이고, 상수 멤버 함수가 객체의 상수성을 유지한 채로 동작할 수 있도록 하며, 무효참조 핸들이 생기는 경우를
최소화할 수 있습니다.
ex)
#include <iostream>
#include <memory>
using namespace std;
class Point
{
private:
int x, y;
public :
Point() : x(0), y(0) { }
Point(int _x, int _y) : x(_x), y(_y) { }
Point(const Point& arg) { x = arg.x; y = arg.y; }
Point& operator=(const Point& arg) { return Point(arg.x, arg.y); }
~Point() {}
};
class RectData
{
public:
Point ulhc;
Point lrhc;
RectData() : ulhc(0, 0), lrhc(0, 0) { }
RectData(const RectData& arg)
{
ulhc = arg.ulhc;
lrhc = arg.lrhc;
}
~RectData() { }
};
class Rectangle
{
private:
shared_ptr<RectData> pData;
public:
Rectangle() {}
~Rectangle() {}
const Point& upperLeft() const { return pData->ulhc; }
const Point& lowerRight() const { return pData->lrhc; }
};
void main()
{
}
'C++ > Effective C++' 카테고리의 다른 글
17.12.05. Effective C++ 5. 구현 (항목30) (0) | 2020.01.15 |
---|---|
17.11.30. Effective C++ 5. 구현 (항목29) (0) | 2020.01.15 |
17.10.23. Effective C++ 5. 구현 (항목27) (0) | 2020.01.15 |
17.10.23. Effective C++ 5. 구현 (항목26) (0) | 2020.01.14 |
17.10.23. Effective C++ 4. 설계 및 선언 (항목25) (0) | 2020.01.14 |