[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