Study/Effective C++

[effective C++] Chapter 03 : 15. 자원 관리 클래스에서 관리되는 자원은 외부에서 접근할 수 있도록 하자

코딩뚜벅이 2023. 8. 13. 20:26

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

  • get() 함수
  • 암시적 변환 함수
  • 이것만은 잊지 말자 !

get() 함수

 아래와 같이 스마트 포인터를 사용하여 함수 호출 결과를 담고, 어떤 동작을 하는 함수를 정의하여 그 인자로 스마트 포인터를 넘겼을 때의 결과를 보자.

 

 

 위에서 daysHeld 함수는 Investment* 타입의 포인터를 원하는데 shared_ptr을 인자로 넘기고 있기 때문에 에러가 발생한다. 이를 해결하기 위해서 명시적 변환 혹은 암시적 변환이 필요한데,  shared_ptr과 auto_ptr은 get()이라는 멤버 함수를 통해 명시적 변환을 수행할 수 있게 제공해주고 있다. get() 함수를 통해 우리는 스맡트 포인터 객체에 들어 있는 실제 포인터의 사본을 얻을 수 있다. 사용법은 아래와 같다.

 

 

 


 

암시적 변환 함수

위에서 살펴본 get() 함수는 명시적 변환의 형태이고, 제대로 된 스마트 포인터는 암시적 변환도 제공할 수 있어야 한다. 아래 코드를 확인해보자.

 

 

 RAII 객체 안에 있는 실제 자원을 얻어낼 필요가 종종 생기기 때문에, RAII 클래스를 설계하면서 암시적 변환 함수를 제공하여 자원 접근을 매끄럽게 만들어야 하는 경우 역시 생길 수 있다. 예를 들어 아래의 코드를 살펴보자.

 

 

 위 코드는 C API로 직접 조작이 가능한 폰트를 RAII 클래스로 둘러싸는 경우이다. 만약 Font 객체를 FontHandle 로 변환해야하는 경우가 생긴다면 우리는 아래와 같이 get() 함수를 통해 명시적 변환을 할 수 있다.

 

 

 하지만 변환 때마다  get() 함수를 호출해주는 것이 귀찮다면 우리는 FontHandle에서 Font로의 암시적 변환 함수를 Font 클래스에서 제공하도록 할 수 있다. 예시는 아래와 같다.

 

 

 

암시적 변환 함수 덕에 훨씬 쉬워지고 코드가 자연스러워지는 것은 맞지만 마냥 좋은 것은 아니다.

 

 

 위와 같이 Font를 사용하고 싶었던 부분에서 FontHandle로의 변환이 이루어지며 원치 않는 결과를 야기하는 경우 역시 발생할 수 있다. 따라서 RAII 클래스를 실제 자원으로 바꾸는 방법으로 명시적 방법을 제공할 것인지 암시적 변환을 허용할 것인지에 대한 결정은 해당 클래스만의 특정 용도와 사용 환경을 고려해야 한다.

 


 

이것은 잊지 말자 !

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

 

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