chrise chrise - 17 days ago 5
C++ Question

c++ how to implement a switch between class members

I am very new to c++ so I am trying to get a feeling of how to do things the right way in c++. I am having a class that uses one of two members. which one gets determined at instantiation. It looks something like

main() {
shared_pointer<A> a = make_shared<A>();
if ( checkSomething ) {
a->setB(make_shared<B>());
} else {
a->setC(make_shared<C>());
}
a->doStuff();

class A {
public:
doStuff() {

/*here I want to do something like call
m_b->doStuff() if this pointer is set and m_c->doStuff() if
that pointer is set.*/

}

setB( B* p ) { m_b = p; }
setC( C* p ) { m_c = p; }
B* m_b;
C* m_c;
}
}
B and C are some classes with doStuff() member function


There are many members like doStuff. Ideally I would avoid checking for nullptr in each of them. What is the best/most efficient/fastest way to create a switch between those two members?

Is there a way to use a static pointer so that I have a member

static **int m_switch;


and do something like

m_switch = condition ? &m_b : &m_c;


and call

*m_switch->doStuff();


Does the compiler here also replace the extra pointer hop because it is a static?

Is there any other smart way to do those switches?

Answer

Normally, class A would be an interface class, which both B and C would inherit and implement. But it sounds like you cannot do this for whatever reason.

Since you want to emulate this, you can start by making the interface:

class A_interface
{
public:
    virtual void doStuff() = 0;
    virtual void doThings() = 0;
    virtual void doBeDoBeDo() = 0;
};

And then you make a template wrapper:

template< class T >
class A : public A_interface
{
public:
   void doStuff() override { target.doStuff(); }
   void doThings() override { target.doThings(); }
   void doBeDoBeDo() override { target.doBeDoBeDo(); }

private:
    T target;
};

This essentially does half of what your own example class A was trying to do, but now you can use a common interface. All you need to do is construct the correct templated version you want:

std::shared_ptr<A_interface> a;

if( checkSomething ) {
    a = std::make_shared<A<B>>();
} else {
    a = std::make_shared<A<C>>();
}

a->doStuff();
Comments