15: 자원 관리 클래스에서 관리되는 자원은 외부에서 접근할 수 있도록 하자
자원 관리 객체를 쓰더라도 실제 자원을 사용해야 할 일이 더러 있다.
int dayHeld(const Investment* pi)
tr1::shared_ptr<Investment> pInv(createInvestment());
iint days = daysHeld(pInv); // 에러
daysHeld 함수는 Investment* 타입의 객체 포인터를 원하지만 tr1::shared_ptr<Investment> 타입의 객체를 넘기고 있기에 컴파일이 안 된다.
RAII 클래스의 객체를 그 객체가 감싸고 있는 실제 자원으로 변환할 방법이 필요하다. 방법은 두 가지이다.
- 명시적 변환(explicit conversion)
- shared_ptr과 auto_ptr은 명시적 변환을 수행하는 get이라는 멤버함수를 제공한다. 이 함수를 사용하면 각 타입으로 만든 스마트 포인터 객체에 들어 있는 실제 포인터(의 사본)을 얻어낼 수 있다.
- 암시적 변환(implicit conversion)
- shared_ptr과 auto_ptr은 포인터 역참조 연산자(opeartor-> 및 operator*)도 오버로딩하고 있다.
int days = daysHeld(pInv.get());
int days = daysHeld(*pInv);
RAII 클래스만의 특정한 용도와 사용 환경에 따라 명시적 변환을 제공할 것인지 아니면 암시적 변환을 허용할 것인지에 대한 결정이 달라진다. 늘 그런 것은 아니지만, 암시적 변환보다는 get 등의 명시적 변환 함수를 제공하는 쪽이 나을 때가 많다.
RAII 클래스에서 자원 접근 함수를 열어 주는 설계가 혹시 캡슐화에 위배되는 것은 아닐까? 그렇긴 하지만, 틀려먹은 설계도 아니다. 애초부터 데이터 은닉의 목적이 아닌, 원하는 동작(자원 해제)이 실수 없이 이루어지도록 하면 OK다.
이것만은 잊지 말자!
- 실제 자원을 직접 접근해야 하는 기존 API들도 많기 때문에, RAII 클래스를 만들 때는 그 클래스가 관리하는 자원을 얻을 수 있는 방법을 열어 주어야 한다.
- 자원 접근은 명시적 변환 혹은 암시적 변환을 통해 가능하다. 안정성만 따지면 명시적 변환이 대체적으로 더 낫지만, 고객 편의성을 놓고 보면 암시적 변환이 괜찮다.
'C++ > Effective C++' 카테고리의 다른 글
[Effective C++] 17: new로 생성한 객체를 스마트 포인터에 저장하는 코드는 별도의 한 문장으로 만들자 (0) | 2023.10.14 |
---|---|
[Effective C++] 16: new 및 delete를 사용할 때는 형태를 반드시 갖추자 (1) | 2023.10.13 |
[Effective C++] 14: 자원 관리 클래스의 복사 동작에 대해 진지하게 고찰하자 (1) | 2023.10.10 |
[Effective C++] 13: 자원 관리에는 객체가 그만! (0) | 2023.10.09 |
[Effective C++] 12: 객체의 모든 부분을 빠짐없이 복사하자 (0) | 2023.10.08 |