우리가 스마트포인터를 이용하여 객체를 관리할때

 

즉!

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 클래스를 만들 때는 그 클래스가 관리하는 자원을 얻을 수 있는 방법을 열어 주어야 합니다. 

◆ 자원 접근은 명시적 변환 혹은 암시적 변환을 통해 가능합니다. 안전성만 따지면 명시적 변환이 대체적으로 더 낫지만, 고객 편의성을 놓고 보면 암시적 변환이 괜찮습니다.


+ Recent posts