Consider the following classes, which employ the Curiously Recurring Template Pattern (CRTP):
template <typename T> class Base { public: virtual ~Base() {} void typeOfThis() { cout << "Type of this: " << typeid(this).name() << '\n'; cout << "Type of *this: " << typeid(*this).name() << '\n'; } void callFuncOfTemplateParam() { static_cast<T*>(this)->hello(); } }; class Derived : public Base<Derived> { public: void hello() { cout << "Hello from Derived!" << '\n'; } }; When I execute the following:
Base<Derived> * basePtrToDerived = new Derived(); basePtrToDerived->typeOfThis(); basePtrToDerived->callFuncOfTemplateParam(); I obtain these results, which make sense to me:
Type of this: P4BaseI7DerivedE Type of *this: 7Derived Hello from Derived! Clearly, the call to hello inside of callFuncOfTemplateParam succeeds because the this pointer points to an instance of Derived, which is why I am able to cast the this pointer from the type Base<Derived>* to the type Derived*.
Now, my confusion arises because when I execute the following:
Base<Derived> * basePtrToBase = new Base<Derived>(); basePtrToBase->typeOfThis(); basePtrToBase->callFuncOfTemplateParam(); I obtain the following results:
Type of this: P4BaseI7DerivedE Type of *this: 4BaseI7DerivedE Hello from Derived! The types of this and *this make sense, but I don't understand how the call to hello succeeds. this doesn't point to an instance of Derived, so why am I able to cast the type of this from Base<Derived> to Derived?
Note that I also replaced the call to static_cast<T*>(this)->hello(); with a call to dynamic_cast<T*>(this)->hello();, and I still obtain the same results. I expected the dynamic_cast to return a nullptr, but it doesn't.
I am very surprised by these results. Thank you for any help clarifying my doubts!