우리가 스마트포인터를 이용하여 객체를 관리할때
즉!
std::tr1::shared_ptr<Investment> pInv( createInvestment() );
위와 같이 스마트 포이터를 선언하고, Investment 클래스를 사용하는 함수를 만들려고 할 때,
int daysHeld(const Investment *pi);
이렇게 선언한 뒤
int days = daysHeld(pInv);
이렇게 사용하는 것이 일반적일 것이다. 그러나 이 구문은 에러가 난다.
왜냐하면 daysHeld의 전달인자는 Investment의 포인터형이지만, pInv는 std::tr1::shared_ptr<Investment> 타입의 객체이기 때문에 타입이 맞지 않아 에러가 발생하는 것이다.
그래서,
스마트 포인터가 가리키는 실제 자원으로 변환해야 할 필요가 있는데, 여기서 방법은 명시적 변환과 암시적 변환이 있다.
첫째, 명시적 변환
std::auto_ptr와 std::tr1::shared_ptr에는 실제 포인터를 명시적으로 얻을 수 있는 get()멤버함수를 제공한다.
둘째, 암시적 변환
std::auto_ptr와 std::tr1::shared_ptr에는 자신이 관리하는 실제 포인터에 대한 암시적 변환도 쉽게 얻을 수 있게 operator-> 와 operator* 을 정의해 두었습니다.
( ex. 사용예 pi->isEmpty(), *(pi).isEmpty() 드러나 있지 않지만 변환이 실제 포인터로 변환이 이루어진 상태에서 자원에 접근 하고 있다. )
또한, 암시적 변환 함수를 이용해서 스마트 포인터 변수명만으로도 실제 포인터를 얻어낼수 있습니다.
operator 변환될 자료형 () const; ( ex. operator FontHandle() const { return f; } )
위의 변환을 사용하게 되면, 암시적으로 쉽게 내부 포인터를 얻어 올수 있게 되지만, 원하지 않는 변환이 일어 날 수도 있기때문에 조심해야한다.
1 2 3 4 | Font f1(getFont()); ... FontHandle f2 = f1; /** * 원래의도는 Font 객체를 복사하는 것이었는데 * 엉뚱하게도 f1이 FontHandle로 바뀌고 나서 * 복사되어 버림 */ |
꼼꼼히 제대로 설계된 클래스가 그렇듯, 사용자가 볼 필요가 없는 데이터는 가리지만 고객 차원에서 꼭 접근해야 하는 데이터는 열어 주는 것입니다.
이것 만은 잊지 말자!
◆ 실제 자원을 직접 접근해야 하는 기존 API들도 많기 때문에, RAII 클래스를 만들 때는 그 클래스가 관리하는 자원을 얻을 수 있는 방법을 열어 주어야 합니다.
'0x0001 > Effective C++' 카테고리의 다른 글
[Effective C++] 항목 17 : new로 생성한 객체를 스마트 포인터에 저장하는 코드는 별도의 한 문장으로 만들자 (0) | 2019.02.13 |
---|---|
[Effective C++] 항목 16 : new 및 delete를 사용할 때는 형태를 반드시 맞추자 (0) | 2019.02.13 |
[Effective C++] 항목 14 : 자원 관리 클래스의 복사 동작에 대해 진지하게 고찰하자 (0) | 2019.02.12 |
[Effective C++] 항목 13 : 자원 관리에는 객체가 그만! (0) | 2019.02.12 |
[Effective C++] 항목 12 : 객체의 모든 부분을 빠짐없이 복사하자 (0) | 2019.02.12 |