If you want no performance penalties, you could use CRTP:
template <typename Derived>
class A {
public:
A() {}
void b() { static_cast<Derived*>(this)->c(); }
void c() { std::cout << "1\n"; }
};
class B : public A<B> {
public:
void c() { std::cout << "2\n"; }
};
int main() {
B b;
b.b();
}
Live example: https://onlinegdb.com/SJzxbtqjz
However, this might not be what you want - it all depends on your use case, which I cannot tell from your question. Make sure you read the pitfalls section on the wikipedia page I linked above:
One issue with static polymorphism is that without using a general
base class like "Shape" from the above example, derived classes cannot
be stored homogeneously as each CRTP base class is a unique type. For
this reason, it is more common to inherit from a shared base class
with a virtual destructor, like the example above.
EDIT:
Otherwise, you'll need to do what you suggested, and pay the price of going through a function pointer. However, if the function you are calling is not something very simple, you probably won't see a difference in performance.
EDIT 2:
The compiler will completely inline the call toc()
with appropriate optimizations.
GCC 7.3 with -O2 optimization flag, and a bit simpler code (just to avoid complexity of std::cout
):
template <typename Derived>
class A {
public:
A() {}
int b() { return static_cast<Derived*>(this)->c(); }
int c() { return 1; }
};
class B : public A<B> {
public:
int c() { return 2; }
};
int f() {
B b;
return b.b();
}
will generate no code for class B
, and generate the following assembly for f
:
f():
mov eax, 2
ret
Live example: https://godbolt.org/g/Mh99bZ