This is CRTP usage for static polymorphism but without implementation of a derived function. Compiles both in gcc and visual studio. Why?
#include <iostream>
template <class Derived>
class Base
{
public:
void method1()
{
static_cast<Derived*>(this)->method1(开发者_开发问答);
}
void method2()
{
static_cast<Derived*>(this)->method2();
}
};
class Derived1: public Base<Derived1>
{
public:
void method1()
{
std::cout << "Method 1 of Derived1 executed.\n";
}
};
int main(int argc, char *argv[])
{
Derived1 d1;
d1.method1();
d1.method2();
return 0;
}
Follow up question: How to I make this type safe? That is, If someone forgets to implement method2, I would like the compiler to catch it. I don't want this to blow up at runtime.
I think the reason that this is valid is that if you instantiate this code:
void method2()
{
static_cast<Derived*>(this)->method2();
}
where Derived
does not have an implementation of method2()
will essentially be a glorified self-recursive call. The reason here is that in Derived1
, there is indeed a member function called method2
, namely the one inherited from the base class.
I tried running this code, and sure enough the call to method2
caused a stack overflow from self-recursion.
Normally, the CRTP avoids this by not having the base class function call a derived class function of the same name. That way, if the derived class is missing a particular function, the call triggers a compiler error. In your case, this doesn't happen because the function itself could be referenced indirectly from the base class.
Derived1 d1;
d1.method2();
Even though Derived1
doesn't define method2()
, it gets it by inheriting Base
anyway. That is why it compiles and runs. d1.method2()
actually calls Base::method2()
, which again calls itself. It's a recursive call.
精彩评论