출처 : http://www.informit.com/articles/article.aspx?p=31529&seqNum=7함수 인자에서 형변환과 유저 타입 형변환 연산자가 어떻게 작용하는지 설명하는 좋은 글이라 생각한다something* 타입 형변환을 SmartPtr 포인터에 operator something* 타입으로 정의 선언 해 놓으면그 함수를 fun(sp)시 그 연산자 호출 된다 암시적 형변환을 통해 (something*)으로의 형변환 연산자를 찾게되고 다시포인터 타입임으로 암시적으로 void* 로 변환된다..7.7 Implicit Conversion to Raw Pointer Types
Consider this code:void Fun(Something* p); ... SmartPtr<Something> sp(new Something); Fun(sp); // OK or error?Should this code compile or not? Following the “maximum compatibility” line of thought, the answer is yes.Technically, it is very simple to render the previous code compilable by introducing a user-defined conversion:template <class T> class SmartPtr { public: operator T*() // user-defined conversion to T* { return pointee_; } ... };However, this is not the end of the story.User-defined conversions in C++ have an interesting history. Back in the 1980s, when user-defined conversions were introduced, most programmers considered them a great invention. User-defined conversions promised a more unified type system, expressive semantics, and the ability to define new types that were indistinguishable from built-in ones. With time, however, user-defined conversions revealed themselves as awkward and potentially dangerous. They might become dangerous especially when they expose handles to internal data (Meyers 1998a, Item 29), which is precisely the case with theoperator T* in the previous code. That's why you should think carefully before allowing automatic conversions for the smart pointers you design.One potential danger comes inherently from giving the user unattended access to the raw pointer that the smart pointer wraps. Passing the raw pointer around defeats the inner workings of the smart pointer. Once unleashed from the confines of its wrapper, the raw pointer can easily become a threat to program sanity again, just as it was before smart pointers were introduced.Another danger is that user-defined conversions pop up unexpectedly, even when you don't need them. Consider the following code:SmartPtr<Something> sp; ... // A gross semantic error // However, it goes undetected at compile time delete sp;The compiler matches operator delete with the user-defined conversion to T*. At runtime, operator T*is called, and delete is applied to its result. This is certainly not what you want to do to a smart pointer, because it is supposed to manage ownership itself. An extra unwitting delete call throws out the window all the careful ownership management that the smart pointer performs under the covers.There are quite a few ways to prevent the delete call from compiling. Some of them are very ingenious (Meyers 1996). One that's very effective and easy to implement is to make the call to deleteintentionally ambiguous. You can achieve this by providing two automatic conversions to types that are susceptible to a call to delete. One type is T* itself, and the other can be void*.template <class T> class SmartPtr { public: operator T*() // User-defined conversion to T* { return pointee_; } operator void*() // Added conversion to void* { return pointee_; } ... };A call to delete against such a smart pointer object is ambiguous. The compiler cannot decide which conversion to apply, and the trick above exploits this indecision to good advantage.Don't forget that disabling the delete operator was only a part of the issue. Whether to provide an automatic conversion to a raw pointer remains an important decision in implementing a smart pointer. It's too dangerous just to let it in, yet too convenient to rule it out. The final SmartPtr implementation will give you a choice about that.However, forbidding implicit conversion does not necessarily eliminate all access to the raw pointer; it is often necessary to gain such access. Therefore, all smart pointers do provide explicit access to their wrapped pointer via a call to a function:void Fun(Something* p); ... SmartPtr<Something> sp; Fun(GetImpl(sp)); // OK, explicit conversion always allowedIt's not a matter of whether you can get to the wrapped pointer; it's how easy it is. This may seem like a minor difference, but it's actually very important. An implicit conversion happens without the programmer or the maintainer noticing or even knowing it. An explicit conversion—as is the call to GetImpl—passes through the mind, the understanding, and the fingers of the programmer and remains written in the code for everybody to see it.Implicit conversion from the smart pointer type to the raw pointer type is desirable, but sometimes dangerous. SmartPtr provides this implicit conversion as a choice. The default is on the safe side—no implicit conversions. Explicit access is always available through the GetImpl function.
2015년 1월 28일 수요일
user defined conversion ,void pointer ,Smart Pointer에서의 쓰임
피드 구독하기:
댓글 (Atom)
댓글 없음:
댓글 쓰기