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

수민이슈·2023년 3월 21일
0

Effective C++

목록 보기
15/30
post-thumbnail

스콧 마이어스의 Effective C++을 읽고 개인 공부 목적으로 요약 작성한 글입니다!

💡 실제 자원을 직접 접근해야 하는 기존 API들도 많기 때문에,
RAII 클래스를 만들 때는 그 클래스가 관리하는 자원을 얻을 수 있는 방법을 열어주어야 한다!
💡 자원 접근은 명시적 변환 혹은 암시적 변환을 통해 가능하다
💡 안전성만을 고려하면 명시적 변환이 낫지만, 고객 편의성을 두고 보면 암시적 변환이 괜찮다!


🖊️ 실제 자원에 접근해야 하는 경우

std::tr1::shared_ptr<Investment> pInv(CreateInvestment());

int daysHeld(const Investment* pi);

int days = daysHeld(pInv);				// Error!

이런 상황이 있을 수가 있슴

가끔 API들이 이렇게 객체를 직접 참조하도록 만들어진 경우가 있음.

daysHeld가 원하는건 Investment* 타입의 객체인데,
pInv는 shared_ptr<Investment>의 객체잖어,,
그니까 에러가 나는거임!!


🖊️ RAII 클래스의 객체를 실제 자원으로 변환

명시적 변환 (explicit conversion)

get() 멤버함수 사용

스마트 포인터 객체에 들어있는 실제 포인터의 사본을 얻을 수 있다.

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

암시적 변환 (implicit conversion)

포인터 역참조 연산자

스마트 포인터 클래스에는 포인터 역참조 연산자를 오버로딩 하고 있다.
ex) operator->, operator*

class Investment {
public:
	bool isTaxTree() const;
    ...
};

Investment* createInvestment();

shared_ptr<Investment> pi1(createInvestment());
bool texable1 = !(pi1->isTaxFree());

...

auto_ptr<Investment> pi2(createInvestment());
bool texable2 = !((*pi2).isTaxFree());
}

워뗘.
shared_ptr에서는 operator->을 써서 자원에 접근하고,
auto_ptr에서는 operator*을 써서 자원에 접근했다.
물론 예시니까 둘이 바꿔도 된당!

암시적 변환 함수

FontHandle getFont();

void releaseFont(FontHandle fh);

class Font {
public:
	explicit Font(FontHandle fh) : f(fh) {}
    ~Font() { releaseFont(f); }
   
   FontHandle get() const { return f; } 			// 명시적 변환 함수
   
   operator FontHandle() const { return f; } 		// 암시적 변환 함수
   
private:
	FontHandle f;									// 실제 자원
};
void ChangeFontSize(FontHandle f, int newSize);

Font f(getFont());
int newFontSize;
...
ChangeFontSize(f.get(), newFontSize);

명시적 변환 함수가 get 멤버 함수를 쓴다고 했자나
근데 그러면 변환할 때마다 .get()을 매번 호출해야 하니까,, 넘 번거로움

그래서 암시적 변환 함수를 Font에서 제공한다 치면,

Font f(getFont());
int newFontSize;
...
changeFontSize(f, newFontSize);

이렇게 같은 상황에서 뚝딱.
Font에서 FontHandle로 변환을 해줘부럿다.

근데 이렇게 되면

Font f1(getFont());
...
FontHandle f2 = f1;

이런 상황에서,,
봐바
Font 타입의 f1을 복사해주고 싶었는데
FontHandle 타입으로 변해버렸잖어,,

이렇게,,
암시적 변환을 하면 원하지 않는 타입 변환이 일어날 수도 있다.

그래서 용도와 사용 환경에 따라서 명시적 / 암시적 변환 중 뭘 할지 고르면 된당!


😊 느낀점

.get() 으로 객체를 얻어오기
난 항상 명시적 변환을 했었다
아무래도,, 그게 익숙하고 좀 더 직관적이다
근데 그냥 명시적 변환을 쓰는게 좋을 것 같다
편의성은.. 솔직히 잘 몰겟다 ㅋ ㅋ

0개의 댓글