-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Jonathan Bartlett <johnnyb@eskimo.com> writes:
[color=blue]
> To do OO in C, you usually do something like this:
>
> The C Version:
> --------------
> struct foo;
> struct vtable_foo
> {
> void (*bar)(struct foo*);
> void (*abc)(struct foo*);
> };[/color]
[color=blue]
> struct vtable_foo __vtable_foo;
> /* class initializer -- must be run EXACTLY ONCE before creating any
> instances of foo */
> void initialize_foo_class()
> {
> __vtable_foo.bar = foo_bar;
> __vtable_foo.abc = foo_abc;
> }
>
> /* constructor */
> void foo_initialize(struct foo *f)
> {
> f->vtbl = &__vtable_foo;
> f->a = 0;
> }
>
> struct doo;
> struct vtable_doo
> {
> void (*bar)(struct doo*);
> void (*abc)(struct doo*);
> void (*xyz)(struct doo*);
> };
> struct vtable_doo __vtable_doo;[/color]
[color=blue]
> void initialize_doo_class()
> {
> /* inherited from foo */
> __vtable_doo.bar = doo_bar; /* overriden in doo */
> __vtable_doo.abc = foo_abc;
>
> /* new in doo */
> __vtable_doo.xyz = doo_xyz;
> }
>
> void doo_initialize(struct doo *d)
> {
> d->vtbl = &__vtable_doo;
> d->a = 0;
> d->b = 0;
> }[/color]
The problem with this scheme is that your initialisers don't take a
vtable as a parameter. This prevents "chaining up" in inherited
vtables. You had to duplicate vtable_foo /by hand/ in vtable_doo.
This is messy, and won't scale: if you now alter vtable_foo, your code
is broken (you can't cast between the two types). What you really
want is:
typedef struct _FooClass
{
void (*bar)(struct foo*);
void (*abc)(struct foo*);
} FooClass;
typedef struct _DooClass
{
FooClass parent;
void (*xyz)(struct doo*);
} DooClass;
You can now freely cast between them, with no worries about a changing
API.
[color=blue]
> The problem w/ this approach is (a) its messy and error prone, and (b)
> it only supports direct single-line inheritance. If you want to use
> multiple inheritance or even mixin classes (abstract classes like java
> interfaces), it gets much trickier, and (c) you have to do a LOT of
> writing.[/color]
There are good libraries to help with this, such as GObject. They
handle interfaces, though multiple inheritance is asking too much (and
is of dubious value in any case).
Regards,
Roger
- --
Roger Leigh
Printing on GNU/Linux?
http://gimp-print.sourceforge.net/
Debian GNU/Linux
http://www.debian.org/
GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Processed by Mailcrypt 3.5.8 <http://mailcrypt.sourceforge.net/>
iD8DBQFClLorVcFcaSW/uEgRAolJAKDmSCdtuD9jitRBDdBPigTTC2XqBQCgvTAq
O4V8mnpDwi71CqDCaRX4FQo=
=eDbg
-----END PGP SIGNATURE-----