Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Polymorphic member class for non-virtual base

First if all, of the polymorphism answers I find, it's always like "if the base function is not virtual and the derived object is stored in a pointer of type base, then you cannot call the derived function". But they never tell you what to do when you want to do exactly that. And that's what I need to do.

I have a base class B that I have no control over. It's open source (TwoWire from Arduino library) and it will not work for others if I make local modifications.

I have a derived class D and a user class U that I both have control over.

In effect, I want the user to use my class U transparently with either a B or a D as parameter, store it in a member, and use it in member functions.

My futile attempt before learning virtual is required on the base class:

#include <iostream>

using namespace std;

class B {
public:
    void foo() { cout << "base foo\n"; };
};

class D : public B {
public:
    void foo() { cout << "derived foo\n"; };
};

class U {
public:
    U(B *b) : b(b) { }
    void work() { b->foo(); }
private:
    B *b;
};

int main() {
    B b; U u1{&b}; u1.work(); // "base foo"
    D d; U u2{&d}; u2.work(); // I need this to somehow print "derived foo"
    return 0;
}

I could solve this by making an abstract wrapper class and two sub-classes that wrap either B or D, but that would bring the total number of custom classes to 5. I'm hoping for a solution of just 2 custom classes (or at most 3).

N.B. I'm just starting to learn C++, coming from Java

like image 399
Mark Jeronimus Avatar asked Oct 15 '22 09:10

Mark Jeronimus


1 Answers

Since making the member function virtual is not a possibility, you have to simulate dynamic dispatch with type erasure:

#include <functional>

class U {
public:
    template <class C>
    U(C* p)
        : f{[p]{ p->foo(); }}
    {
    }
    void work()
    {
        f();
    }
private:
    std::function<void()> f;
};

(live demo)

Note that functions in Java are virtual by default. Not in C++.

like image 95
L. F. Avatar answered Oct 18 '22 13:10

L. F.