본문 바로가기
서적 정리/Effective C++

15.자원 관리 클래스에서 관리되는 자원은 외부에서 접근할 수 있도록 하자

by 민돌이2 2021. 12. 11.

스마트 포인터(auto_ptr, tr1::shared_ptr)는 스마트 포인터 타입의 객체를 반환한다.

std::tr1::shared_ptr<Investment> pInv;

int daysHeld(const Investment* pi);

int days = datysHeld(pInv); //에러

에러 설명

즉, 실제 자원으로 변환할 방법이 필요하다.

 

스마트 포인터를 실제 자원으로 변환할 일반적인 방법은 두 가지가 있다.

1.명시적 변환(explict conversion)

스마트 포인터에는 명시적 변환을 수행하는 get 멤버 함수가 있다. get 함수를 사용하면 포마트 포인터 객체에 들어있는 실제 포인터의 사본을 얻을 수 있다.

int days = daysHeld(pInv.get());

 

2.암시적 변환(implict conversion)

스마트 포인터 클래스라면 거의 포인터 역참조 연산자(operator-> 및 operator*)도 오버로딩하고 있다.

class Investment //투자를 모델링하는 클래스 계통의 최상위 클래스
{
public: 
	bool isTaxFree()  const;
}; 

shared_ptr<Investment> pInv;
	
bool taxable1 = pInv->isTaxFree(); //operator->
bool taxable2 = (*pInv).isTaxFree(); //operator*

 

책을 보다 보니 신박한게 있었다.

테스트를 해보니 스마트 포인터말고도 멤버 데이터 또한 잘 먹히는데, 암시적 변환을 사용한 것이다.

내 포트폴리오에 쓸법한 예를 적어보자면

class HitBox { }; //히트 박스 관리 클래스

class Player
{
public:
	HitBox GetHitBox() const { return hitBox; } //명시적 변환
	operator HitBox() const { return hitBox; } //암시적 변환

private:
	HitBox hitBox; //히트 박스 객체
};

/* @brief : 모델간 충돌 체크 */
/* @param player : 플레이어의 히트 박스 */
/* @param monster : 몬스터의 히트 박스 */
bool CheckCollision(HitBox player, HitBox monster) { }

int main()
{
	Player player;
	CheckCollision(player, player.GetHitBox());

	system("Pause");
	return 0;
}

몬스터 객체를 만들기 귀찮아서 CheckCollision함수에 둘 다 플레이어를 넣긴 했다.

CheckCollision함수의 매개 변수는 HitBox두 개를 받는데, Player.GetHitBox()는 Player 클래스안에 GetHitBox라는 함수에서 Player의 hitBox를 반환하게 구현해놨기 때문에 이상한 점을 느끼지 못한다.

여기서 신박한 것은 첫 번째 매개 변수로 넣은 player이다. Player의 객체인 player을 넣었는데 왜 매개변수가 HitBox인 곳에 에러가 발생하지 않는가?

operator HitBox()가 이 역할을 한다. 코드는 깔끔해지고 유연해진다는 느낌은 든다.

 

하지만 실수를 저지를 여지가 많아진다. Player을 쓰려고 한 부분인데 HitBox로 바뀔 수 있다는 것이다.

HitBox hb = player;

암시적 변환으로 player가 HitBox로 변환하기 때문에 컴파일에러도 없고, 링커도 잡아내지 못한다.

편의성을 위해 안전성을 포기한 느낌이다.

 

이것만은 잊지 말자

실제 자원을 직접 접근해야 하는 기존 API들도 많기 때문에, RAII 클래스를 만들 때는 그 클래스가 관리하는 자원을 얻을 수 있는 방법을 열어 주어야 한다.

자원 접근은 명시적 변환 혹은 암시적 변환을 통해 가능하다.

안정성만 따지면 명시적 변환이 대체적으로 낫지만, 편의성을 놓고 보면 암시적 변환이 괜찮다.

728x90

댓글