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!)
问题:
回答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.
回答2:
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.