Adding an instance of a class derived from an interface to an interface pointer table

advertisements

I have an interface struct called IFoo.

struct IFoo
{
    void someFunc();

    virtual ~IFoo()
    {
    }
};

I have multiple structs derived from the interface. Each struct could have different constructors.

struct FooA : IFoo
{
    FooA(int i1, int i2)
    {
    }

    void someFunc()
    {
    }

    ~FooA()
    {
    }
};

struct FooB : IFoo
{
    FooB(int i)
    {
    }

    void someFunc()
    {
    }

    ~FooB()
    {
    }
};

I have a struct which (will) contain an array of pointers (in the example, just a single item to keep it simple).

struct FooContainer
{
    IFoo* fooItem;
};

FooContainer knows nothing about the derived instances.

I have written the following code, which appears to work.

Is it valid to set a pointer of IFoo to a pointer of a derived struct (say, FooA) in this manner?

Can anyone please advise if this is a good idea? It SEEMS to work fine... but I would prefer to know now of any problems I might get (memory problems etc) rather than find them further down the line. I know I will need to add missing methods... assignment operators, copy constructor etc :)

struct FooContainer
{
    IFoo* fooItem; // this will be an array of ifoo pointers in actual code

    FooContainer()
        : fooItem(0)
    {
    }

    template <typename T>
    void setFoo(const T& foo)
    {
        delete fooItem;

        fooItem = new T(foo); // this will add the item to the array
    }

    ~FooContainer()
    {
        delete fooItem;
    }
};

To be called like this:

FooContainer fooContainer = FooContainer();
fooContainer.setFoo(FooA(1, 1));

This is not C++11, just in case that matters.


Is it valid to set a pointer of IFoo to a pointer of a derived struct (say, FooA)?

Yes, that is the perfectly right thing to do.

When you have a pointer to a derived type, and assign it to a pointer to one of its base types, the compiler automatically adjusts the pointer as required. Your call to fooContainer.setFoo(FooA(1, 1)) makes the compiler instantiate

void setFoo<FooA>(const FooA& foo)

thus the new and assignment becomes

fooItem = new FooA(foo);

here, new FooA(foo) returns a FooA*, which is implicitly converted to a IFoo* as required by the assignment operator.

The only thing to look out for (and you already did that right), is to declare (and possibly define) a virtual destructor in the base class. This is needed, so that if you delete fooItem, the destructor of the actual object (e.g. FooA::~FooA()) is called.

For the derived classes, you don't need to define empty destructors.