While writing my little API framework I run into a rather strange problem – my smart pointer code started to throw null pointer exception. It only did that when there was an attempt to assign a null pointer to it (that should never happen).
After a bit of debugger investigation I found a bit of code that looked like this:
template CManagedObject<_ParentType, _Type>::CManagedObject(CRefPtr<_ParentType> pParent) : m_pParent(pParent) { this->m_pParent.Cast<CObjectManager>()->AddObject(this); // }
I was quite surprised, because this code never brought any problems. Further investigation (and pointless modifications of this code) brought me to another conclusion (and a snipped of code):
template<_CastType> template<_Type> const _CastType* CPtr<_Type>::Cast(){ return dynamic_cast<_CastType* const>(this->m_pPtr); }
And that was even more surprising – dynamic_cast returned null. The cause was that I forgot to add another base class (CObjectManager<CBuffer>) to the class I was building, and dynamic_cast failed to cast it – because it couldn’t. There was no definition to cast that kind to object to this one.
But in normal circumstances dynamic_cast should report an syntax-compile time error, when there is no way perform proper cast, right?
Not quite – template classes are more complex entities that can take many forms – it would be to time consuming to check all possible outcomes – that’s why on cast failure dynamic_cast returns null. The code that I wrote ages ago and proofed it to death was once more not to blame – I didn’t believe it and wasted about 2-3 hours…