I'm new to learning modern C++ programming. I have read many blogs and questions but haven't found the answer of this question. In C++, compared to final or not virtual function, what is the advantage of CRTP?
When people talk about CRTP, some code like these are often shown as an example:
template<typename Derived>
class Base {
public:
void interface() {
static_cast<Derived*>(this)->implementation();
}
void foo() { ... }
};
class Derived : public Base<Derived> {
public:
void implementation() { ... }
};
int main() {
Derived d;
d.interface();
d.foo();
}
An object d
of class Derived
can use the function foo
from Base
, and Derived
rewrites the function interface
. They don't search vtable because these are not virtual function.
But I think that, when I use inherit, I can achieve the same effect.
class Base1 {
public:
virtual void interface() = 0;
void foo() { ... }
};
class Derived1 : public Base1 {
public:
void interface() final { ... }
};
int main() {
Derived1 *d1 = new Derived1();
d1->interface();
d1->foo();
}
In those code, when d1
call function interface()
, although the function is a virtual function, compiler can recognize that it is actually the function of class Derived1
because I mark final
. And d1
can also call function foo
from Base1
without searching vtable because foo
is not virtual function.
But in the case, I have not used polymorphism. But Base
is a template class. It is Base<Derived>
. We actually has the information that it is Derived
and we can't use a common pointer Base*
which point to Base<A>
and Base<B>
at same time. I think compare it and Base*
in inheritance is not fair. It should be compared to Derived
in inheritance. What I mean is, when we can get type Base<Derived>
, we can also get type Derived*
.
Then, in my opinion, the difference between these two ways to rewrite and share common code is only that inherit will add a vtable at the header of derived class. So these two ways may have some differences in memory usage and running speed due to the different memory sizes. These memory are used to help us point to the subclass through the parent class pointer and perform virtual function calls when we need it. If there are no such situation in code, we choose CRTP, otherwise inherit.
Is my idea correct? What other things can CRTP do that inheritance cannot do?
virtual
functions cannot be templates. CRTP can call template functions from derived classes. Can't recall anything else that you haven't found yourself.