Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call child method from base method without virtual or references

Tags:

c++

Consider the code:

#include <iostream>

class A {
public:
    void g() {std::cout << "Call from A" << std::endl;}
    void f() {g();}
};

class B : public A {
public:
    void g() {std::cout << "Call from B" << std::endl;}
};

int main() {
    B b;
    b.f(); // "Call from A" 
}

If I make A::g() virtual, it outputs "Call from B".

I always understood "virtual" useful when we want an interface to allow polymorphism, say A *a = new B(); a->f(), but this example indicates that virtual is also required in this situation. My understanding of this example is that the call g() on A::f is formally equivalent to this->g(), and this is a pointer.

However, this is not what I really wanted: in my real example, I have a general template class A with a general method A::simulate (say A::f), that uses different methods (say A::g()), some of which are overwritten by subclass (say B). What I wanted was to have the method A::simulate in such a way that the code would be compiled in the subclasses of A as if it has been defined on the subclasses so I don't have the same logic coded multiple-times. How can I do this?

This is because my interface will not require polymorphism because the user will always need to compile the code (i.e. it is header only).

like image 222
Jorge Leitao Avatar asked Jul 01 '15 16:07

Jorge Leitao


1 Answers

You can simply make your base class a CRTP (as you've mentioned it's already a templated class anyway):

#include <iostream>

template<class Derived>
class A {
public:
    void g() {std::cout << "Call from A" << std::endl;}
    void f() { static_cast<Derived*>(this)->g();}
            // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Call g() from Derived
};

class B : public A<B> {
public:
    void g() {std::cout << "Call from B" << std::endl;}
};

int main() {
    B b;
    b.f(); // "Call from B" 
}
like image 116
πάντα ῥεῖ Avatar answered Sep 27 '22 19:09

πάντα ῥεῖ