I have class template acting as base class for derived classes. The idea was to take advantage of "static polymorphic" through the CRTP trick.
#include <iostream>
template <typename T>
class BASE
{
public:
void write() {static_cast<T*>(this)->write(); }
};
class DER1 : public BASE<DER1>
{
public:
void write(){
std::cout << "Calling write() inside DER1 " << number << std::endl;}
private:
int number = 11;
};
I tried 2 different ways of instantiating derived class object, and, I found that one of the two ways is not correct. But I could not understand why.
int main(void) {
BASE<DER1> der1_objA ;
der1_objA.write();
DER1 der1_objB ;
der1_objB.write();
return 0;
}
In fact, I get as output
Calling write() inside DER1 1880535040 [ random number]
Calling write() inside DER1 11 [correct number ]
Can anybody explain me where the issue is? Thank you very much in advance.
When you define an object of type BASE, it is just a BASE, but inside it you case the this pointer to something it is not (DER1), and proceed to use it through that invalid pointer. That is undefined behavior, and garbage is a normal consequence. The only time when CRTP works is when the dynamic type of the object actually is the template parameter passed to the base class. That is, if BASE thinks it really is a DER1, it really must be a DER1. Casting itself to DER1 when it is only BASE and using that pointer for DER1 operations is undefined behavior, not much different from doing this:
You should consider making the BASE constructors have "protected" access level, to prevent the simple cases of misuse. This way the base constructor can only be called by derived objects, so you can't accidentally instantiate the base in isolation:
Then instead of getting garbage, you get: