lp0 on fire

My personal blog

C89-DP: Factory

The goal here is to write a common initializer for multiple classes. In our case it's not gonna look the same as it would in OOP languages because using the base type for initializing and accessing the derived data is going to result in a segmentation fault.

Recap

I'm resuing the IFoo and Foo from C89-OOP: interface inheritance:

typedef struct IFoo IFoo;

struct IFoo
{
    int (*getX)(IFoo* self);
};
typedef struct Foo Foo;

struct Foo
{
    IFoo* ifoo;
    int x;
};

static int Foo_getX(IFoo* self)
{
    Foo* foo = (Foo*)self;
    return foo->x;
}

void Foo_ctor(Foo* self, int x)
{
    static IFoo ifoo = {
        Foo_getX
    };

    self->ifoo = &ifoo;
    self->x = x;
}

The factory

Now we get to the fun part! Here we have to setup two things: the id's we need to signify which instance type we want to create, and a function that actually produces the instance.

enum FactoryIds
{
    FACTORY_FOO = 0
};

void Factory_getFoo(IFoo* result, int id)
{
    switch (id)
    {
        case FACTORY_FOO:
            Foo_ctor((Foo*)result, 1);
            return;
    }
}

For the sake of preventing this article from becoming really long, I only included one type to mess with. You can pretty much initialize any class here as long as it inherits from IFoo.

Usage

Foo foo;
int val;

Factory_getFoo((IFoo*)&foo, FACTORY_FOO);
val = foo.ifoo->getX((IFoo*)&foo);

Conclusion

Is it possible? Yup. It might actually even be useful in production because you can easily set up multiple different data structures with this.