1

It seems that OO in ANSI C is not the favored approach to OO today. Does anyone know of a way to code a simple design pattern using strict ANSI C so I can prove to a friend that it is possible?(Axel-Tobias Schreiners' book got me going on this!)

Eric Steen
  • 719
  • 2
  • 8
  • 19
  • 2
    You can program anything you want in C, you just won't necessarily have any native support for it. I would suggest taking your favourite design pattern, attempting to implement it, and then asking a specific question if/when you get stuck. – Oliver Charlesworth May 20 '12 at 23:42
  • +1 for referencing Axel! He was my grad instructor at RIT. – linuxuser27 May 21 '12 at 00:44
  • 4
    Wait, where does the laptop come into this? Seriously, I'm just confused now. –  May 21 '12 at 00:57
  • I just think it could be really small and amazing, I am trying a simple delegate pattern first, not really C proficient though. – Eric Steen May 21 '12 at 01:05
  • Delegation is just the OO sugar of a simple callback. About the screen, a 11" Mac Book Air has the same resolution as an old 17" lamp shaped iMac. – mouviciel May 21 '12 at 07:23

2 Answers2

1

OO using C can indeed be implemented using function pointers as explained quite well in this SO question.

Using the info from that post, here's how I would implement a Strategy pattern in C using basic inheritance.

Lets use the following C++ as a guide:

class StrategyBase
{
    ...
    StrategyBase();
    virtual void strategyMethod() = 0;
    ...
};

class StrategyDerived
{
    ...
    StrategyDerived();
    void strategyMethod();
    ...
};

And here is the corresponding C code:

typedef struct StrategyBase_t StrategyBase;
struct StrategyBase_t
{
    StrategyBase *base; /* must be first memeber */
    void (*strategyMethod)(const void *self);
};
StrategyBase *newStrategyBase();
void strategyMethod(const void *self);  /* the abstract method */

struct StrategyDerived
{
    StrategyBase *base; /* must be first memeber */
    void (*strategyMethod)(const void *self);
    /* more derived attributes here */
};
typedef struct StrategyDerived_t StrategyDerived;
StrategyDerived *newStrategyDerived();

And here are the function implementations:

void strategyMethod(const void *self)
{
    /* If called with just a StrategyBase, strategyMethod will be NULL, *
     * so perhaps some sort of protection should be added here first    */
    ((StrategyBase*) self)->base->strategyMethod();
}

void strategyMethodDerived(const void *self)
{
    /* Put your implementation here */
}

/* StrategyBase constructor */
StrategyBase *newStrategyBase()
{
    StrategyBase *self = (StrategyBase*) malloc(sizeof(StrategyBase));
    self->base = self; /* See comment below about virtual table */
    self->strategyMethod = NULL; /* StrategyBase is abstract, right? */
    return self;
}

/* StrategyDerived constructor */
StrategyDerived *newStrategyDerived()
{
    StrategyDerived *self = (StrategyDerived*) malloc(sizeof(StrategyDerived));
    self->base = newStrategyBase();
    self->strategyMethod = self->base->strategyMethod = strategyMethodDerived;
    return self;
}

The virtual table implementation is very basic, but should work. Ideally, something more robust should be implemented.

Then you just have to use a pointer to StrategyBase in a Struct that needs a strategy, and there you have a strategy pattern implemented in C. I havent tried compiling it, but this should serve as a good starting point.

Community
  • 1
  • 1
Brady
  • 10,207
  • 2
  • 20
  • 59
0

There's nothing to it; instead of a class Foo, use a struct foo; instead of a constructor Foo::Foo(...), have a function struct foo *foo_new(...).

For a real-life example, see the venerable GObject library.

Asherah
  • 18,948
  • 5
  • 53
  • 72
  • Ya, but I think its more interesting to see how to use inheritance with C. – Brady May 21 '12 at 05:45
  • Inheritance is not a requirement for object-oriented design. (And it can still be done in C, with some effort.) – Asherah May 21 '12 at 05:48