2
votes

I'll try to make my intentions clear since there may be more than one approach to this. To start, I have an abstract base class FooBase with a virtual function SayHi(). Foo1 is one of many derived classes.

class FooBase {
public:
    virtual void SayHi() = 0;
};

class Foo1 : public FooBase {
public:
    virtual void SayHi() {
        std::cout<<"Foo1 says Hi\n";
    }
};

I also have a Component class and sometimes I would like to implement Foo.. classes as Components. I've used a template class so that any subclass of FooBase can have a Component wrapper.

class FooComponentBase : public Component {
public:
    virtual FooBase& GetFoo() = 0;
};

template <class T>
class FooComponent : public FooComponentBase {
private:
    T m_foo;
public:
    virtual FooBase& GetFoo() {return m_foo;}
};

Now FooComponentBase is an interface to components containing any subclass of FooBase:

void DoTest() {
    FooComponentBase* pFooComponent = new FooComponent<Foo1>;
    pFooComponent->GetFoo().SayHi();                            // "Foo1 says Hi"
    delete pFooComponent;
}

So far so good, this works. But it might be neater if FooComponent were inherited from FooBase, so we don't need to go through GetFoo() to access FooBase's methods.

// Inherited version

class FooComponentBase : public Component {};

template <class T>
class FooComponent : public FooComponentBase, public T {};

Unfortunately, FooComponentBase has no access to FooBase even though all of its derived classes do;

void DoTest() {
    FooComponentBase* pFooComponent = new FooComponent<Foo1>;
    pFooComponent->SayHi();     // Error, FooComponentBase has no SayHi() function
    delete pFooComponent;
}

I can't find a way to make this work. It seems like there ought to be a way, maybe using virtual inheritance;

class FooComponentBase : public Component, virtual public FooBase {};

But that won't compile either, since we can't instantiate an abstract class. I hope my intention is clear, I'd like to make FooComponentBase an abstract base class, like FooBase but with Component inheritance, so I can use it to access every flavor of FooComponent. Is there a neat way to do this?

1

1 Answers

2
votes

If you use virtual inheritance in one place, you have to use it everywhere if you want that same base implementation to be used:

class Foo1 : public virtual FooBase {

The other way, which is not as nice but might work out for you, would be to implement all of FooBase's functions in FooComponent:

class FooComponentBase : public Component, public FooBase {
};

template <class T>
class FooComponent : public FooComponentBase {
private:
    T m_foo;
public:
    void SayHi() {m_foo.SayHi();}
};

Or even:

class FooComponentBase : public Component, public FooBase {
};

template <class T>
class FooComponent : public FooComponentBase, public T {
public:
    void SayHi() {T::SayHi();}
};