[linux-l] Re: do{ . } while (0)
Axel Weiß
aweiss at informatik.hu-berlin.de
Do Nov 24 22:17:54 CET 2005
Oliver Bandel schrieb:
> Aber kommt es denn vor, daß man in case-Anweisungen extra Variablen
> braucht?
Ich brauche das überall, wo Polymorphie im Spiel ist. Beispiel:
typedef enum {IS_DERIV1, IS_DERIV2} DerivedType;
typedef struct Base{
DerivedType type;
void *derived;
...
} Base;
typedef struct Derived1{
Base base;
...
} Derived1;
typedef struct Derived2{
Base base;
...
} Derived2;
void Base_Init(Base *self, DerivedType type, void *derived){
self->type = type;
self->derived = derived;
...
}
void Derived1_Init(Derived1 *self){
Base_Init(&self->base, IS_DERIV1, self);
...
}
void Derived1_Function(Derived1 *self){
...
}
void Derived2_Init(Derived2 *self){
Base_Init(&self->base, IS_DERIV2, self);
...
}
void Derived2_Function(Derived2 *self, int argument){
...
}
void Base_Function(Base *self){
switch (self->type){
case IS_DERIV1:
{
Derived1 *derived = (Derived1*)self->derived;
Derived1_Function(derived);
}
break;
case IS_DERIV2:
{
Derived2 *derived = (Derived2*)self->derived;
int magic_argument = ...;
Derived2_Function(derived, magic_argument);
}
break;
}
}
Im Pronzip läuft das ja so wie in C++ mit Vererbung und spätem Binden von
Methoden - nur eben alles explizit. Der funktionale Ansatz
struct Base{
void (*Function)(Base*);
};
mit einer 'abstrakten' Funktion scheitert manchmal daran, dass die
abgeleiteten Klassen unterschiedliche Signaturen benötigen oder gar
gänzlich anders behandelt werden wollen. Hat man gar rekursiv definierte
Strukturen, geht es gar nicht anders.
Das Beispiel ist nicht ganz so theoretisch wie es den Anschein hat, ich
benutze dieses Konzept an mehreren Stellen: kaskadierte Filter, zum
Beispiel, oder bei der Konvertierung von Datenformaten (Bytesex und
Verwandte), bei polymorphen Algorithmen, usw.
Axel
Mehr Informationen über die Mailingliste linux-l