Will line A generate a virtual function call?
Yes. foo_impl()
is virtual and Derived
overrides it. Even though foo_impl()
in Derived
is not explicitly tagged as virtual
, it is in the base class, and this is enough to make it a virtual function.
Does line B fix the issue I brought up in my previous point (if applicable)?
No. It does not matter if the call is on a pointer or on a reference: the compiler still won't know whether you are invoking the function foo_impl()
on an instance of a class that derives from Derived
, or on a direct instance of Derived
. Thus, the call is performed through a vtable.
To see what I mean:
#include <iostream>
using namespace std;
template <class Derived>
class Base {
public:
virtual void foo_impl() = 0;
void foo() {
static_cast<Derived*>(this)->foo_impl();
(*static_cast<Derived*>(this)).foo_impl();
}
};
class Derived : public Base<Derived> {
public:
void foo_impl() {
cout << "Derived::foo_impl()" << endl;
}
};
class MoreDerived : public Derived {
public:
void foo_impl() {
cout << "MoreDerived::foo_impl()" << endl;
}
};
int main()
{
MoreDerived d;
d.foo(); // Will output "MoreDerived::foo_impl()" twice
}
Finally:
Does adding the C++11 final keyword to
foo_impl()
change how the compiler would act in either (or any other relevant) case?
In theory, yes. The final
keyword would make it impossible to override that function in subclasses of Derived
. Thus, when performing a function call to foo_impl()
through a pointer to Derived
, the compiler could resolve the call statically. However, to the best of my knowledge, compilers are not required to do so by the C++ Standard.
CONCLUSION:
In any case, I believe what you actually want to do is not to declare the foo_impl()
function at all in the base class. This is normally the case when you use the CRTP. Additionally, you will have to declare class Base<Derived>
a friend
of Derived
if you want it to access Derived
's private
function foo_impl()
. Otherwise, you can make foo_impl()
public.