Bibliothekserweiterungen in C

07/12/2007 - 19:22 von ram | Report spam
Es geht um die Frage, ob objektorientierte Programmierung
Vorteile gegenüber rein-prozeduraler Programmierung hat.

Besonders interessiert es mich, ob man ein einfaches
und kleines Programmbeispiel dafür finden kann.

Ich glaube, ein Beispiel dafür gefunden zu haben: So daß
man behaupten kann »In rein-prozeduraler Programmierung
geht das nicht.«

Da C wohl die verbreiteteste prozedurale Sprache ist, die
nicht objektorientiert ist, wàre es interessant, ob jemand
vielleicht doch eine Möglichkeit findet, dasselbe in C
zu formulieren. Dann wàre dieses Beispiel widerlegt.

Allerdings wàren dabei solche Lösungen weniger überzeugend,
bei denen in C eine objektorientierte Programmiersprache
»nachgebaut« wird - gedacht ist vor allem an Lösungen, die nur
prozedurales Programmieren nutzen.

Nun also zu der Behauptung über einen Vorteil der
objektorientierten Programmierung:

Es wird behauptet, daß man in der objektorientierten
Programmierung vorhandene Bibliotheken besser erweitern kann,
so daß die Erweiterungen von anderen schon vorhandenen
Bibliotheksfunktionen sofort genutzt werden können.

Beispielsweise führt ein Programm einen neuen Typ für
Positionen ein. Hier als Beispiel in »Java« (einer
»objektorientierten« Programmiersprache):

class Position
{ int x; int y; public java.lang.toString()
{ return java.lang.String.valueOf( x ) +
", " + java.lang.String.valufOf( y ); }}

Dieser Typ besteht aus zwei Koordinaten und einer Funktion
(»Methode«) »toString()«, welche festlegt, wie ein Wert dieses
Typs als Text dargestellt werden kann.

Dann bewirkt dies Auswertung von

java.lang.System.out.println( new Position() )

die Ausgabe von

0, 0

Der neue Typ »Position« hat praktisch die »toString«-Operation
für den Typ »Position« erweitert und die Bibliotheksfunktion
»println« konnte diese Erweiterung sofort nutzen, ohne daß
Änderungen an der Bibliothek nötig wurden.

In der prozeduralen Programmierung in C könnte man eine
Funktion »toString« definieren, die alle bekannten Typen
(eingebaute Typen und struct-Typen einer Bibliothek)
in eine Textdarstellung wandelt. Diese könnte dann von
Bibliotheksfunktionen für (Debug-)Ausgaben genutzt werden.

Aber ein Programm, das einen weiteren Typ (struct) einführt,
könnte solch eine Funktion nicht mehr erweitern.

Ein Programmierer könnte die große »toString«-Funktion àndern,
wenn er Zugriff zu ihrem Quelltext hat. Aber, wenn dann eine
neue Version der Bibliothek herauskommt, müßte er die Änderung
dort erneut ausführen, was offensichtlich nachteilig
(kompliziert und fehlertràchtig) ist. Damit wàre ein Vorteil
der objektorientierten Programmierung gezeigt.

Die Frage ist nun, ob jemand ein C-Programm findet, das zeigt,
daß man dieses Problem mit prozeduraler Programmierung in C
doch elegant lösen kann - auf eine Weise, die ich bisher
übersehen habe.

Das Programm sollte eine »struct« für Positionen definieren,
beispielsweise wie

struct position { int x; int y; }

, oder einen solchen Datentyp auf andere Weise einführen.

Dann sollte es ein Textdarstellungsverfahren festlegen, wie
beispielsweise durch eine Funktionsdefinition wie

void char * string_position( struct position const * const p )
{ char * const buffer = malloc( 32 );
sprintf( buffer, "%d, %d", p->x, p->y );
return buffer; }

(Zur Vereinfachung wurde hier auf korrekte Absicherung
gegen Pufferüberlàufe und 0-Ergebnisse von malloc verzichtet.)

Und nun ist die Behauptung, daß es in C nicht möglich ist, das
ganze auf einfache Weise so zu schreiben, daß eine vorhandene
Bibliotheksroutine zur Ausgabe von beliebigen Daten als Text,
nun die Funktion »string_position« nutzen kann, um dann auch
»position«-Objekte ausgeben zu können.

Diese Frage muß nicht unbedingt durch ein Programmbeispiel
beantwortet werden, das zeigt, daß es doch geht. Es wàre
auch interessant, wenn jemand meint, daß man für so etwas
in C von Anfang an einen anderen Ansatz wàhlt oder wenn
jemand begründen kan, warum solch ein Problem vollkommen
unwichtig oder irrelevant ist.
 

Lesen sie die antworten

#1 Felix Opatz
07/12/2007 - 21:05 | Warnen spam
Stefan Ram wrote:
Es geht um die Frage, ob objektorientierte Programmierung
Vorteile gegenüber rein-prozeduraler Programmierung hat.



Ja, für passende Aufgabenstellungen, sonst nicht. Ich denke das ist
weitgehend unbestritten, allenfalls die Beurteilung ob es eine passende
Aufgabenstellung ist dürfte teilweise recht subjektiv ausfallen. :-)

[...]
Allerdings wàren dabei solche Lösungen weniger überzeugend,
bei denen in C eine objektorientierte Programmiersprache
»nachgebaut« wird - gedacht ist vor allem an Lösungen, die nur
prozedurales Programmieren nutzen.



Damit scheidet mein Vorschlag vermutlich schonmal aus. Denn was Du unten
forderst schreit irgendwie nach einem objektorientierten Ansatz, nàmlich
nach einem Ding, das weiß, wie es ausgegeben werden kann. Bei einer
objektorientierten Sprache wandert diese Funktionalitàt in ein einzelnes
Konstrukt hinein, ohne eine solche Unterstützung hat man getrennte
Konstrukte, die aber in ihrer Zusammenstellung das Ding ergeben.

[...]
Es wird behauptet, daß man in der objektorientierten
Programmierung vorhandene Bibliotheken besser erweitern kann,
so daß die Erweiterungen von anderen schon vorhandenen
Bibliotheksfunktionen sofort genutzt werden können.



Das würde ich noch mit "kommt drauf an" beantworten. So allgemein ist
das nicht gültig.

[Beispiel für ein Objekt mit Methode zur Ausgabe]
In der prozeduralen Programmierung in C könnte man eine
Funktion »toString« definieren, die alle bekannten Typen
(eingebaute Typen und struct-Typen einer Bibliothek)
in eine Textdarstellung wandelt. Diese könnte dann von
Bibliotheksfunktionen für (Debug-)Ausgaben genutzt werden.

Aber ein Programm, das einen weiteren Typ (struct) einführt,
könnte solch eine Funktion nicht mehr erweitern.



Ja. Es sei denn die Funktion ist zur Laufzeit erweiterbar. Denkbar wàre
z.B., daß man neue Typen registrieren kann, und die Funktion zur Ausgabe
einen Zeiger auf eine konkrete Funktion zur Ausgabe dieses Typs erhàlt,
und damit den Wunsch "gib Dich aus" weiterreicht.

Ein Programmierer könnte die große »toString«-Funktion àndern,
wenn er Zugriff zu ihrem Quelltext hat. Aber, wenn dann eine
neue Version der Bibliothek herauskommt, müßte er die Änderung
dort erneut ausführen, was offensichtlich nachteilig
(kompliziert und fehlertràchtig) ist. Damit wàre ein Vorteil
der objektorientierten Programmierung gezeigt.



Ja und nein. Je nachdem ob mein skizzierter Vorschlag für Dich schon
(zu) objektorientiert ist.

[...]
Und nun ist die Behauptung, daß es in C nicht möglich ist, das
ganze auf einfache Weise so zu schreiben, daß eine vorhandene
Bibliotheksroutine zur Ausgabe von beliebigen Daten als Text,
nun die Funktion »string_position« nutzen kann, um dann auch
»position«-Objekte ausgeben zu können.

Diese Frage muß nicht unbedingt durch ein Programmbeispiel
beantwortet werden, das zeigt, daß es doch geht. Es wàre
auch interessant, wenn jemand meint, daß man für so etwas
in C von Anfang an einen anderen Ansatz wàhlt oder wenn
jemand begründen kan, warum solch ein Problem vollkommen
unwichtig oder irrelevant ist.



Also ich würde es, mal grob skizziert, so machen (die Bezeichner
suggerieren bereits, daß es in meiner Sicht um Objekte geht):


#include <stdio.h>

/*** Kann in eigener Übersetzungseinheit verschwinden ***/
#define MAX_TYPES 10

typedef const char *(*tpfPrintMethod)(void *pObject);
static tpfPrintMethod apfPrintMethods[MAX_TYPES];
static int nNextType;

const char *ToString(int nType, void *pObject)
{
return apfPrintMethods[nType](pObject);
}

int RegisterType(tpfPrintMethod pfPrintMethod)
{
apfPrintMethods[nNextType] = pfPrintMethod;
return nNextType++;
}
/********************************************************/

/******* Benutzerdefinierter Typ und Programmcode *******/
struct position { int x; int y; };

const char *string_position(void *pData)
{
struct position *pPosition = (struct position*) pData;

static char buffer[1024];
sprintf(buffer, "%d, %d", pPosition->x, pPosition->y);
return buffer;
}

int main(void)
{
int nMyTypeId;
struct position MyPosition = {0, 0};

nMyTypeId = RegisterType(string_position);

printf("Position: %s", ToString(nMyTypeId, &MyPosition));

return 0;
}
/********************************************************/


Wenn man etwas mehr Hirnschmalz reinsteckt, kann man das mit der TypeId
sicher noch ein bißchen hübscher erledigen (z.B. an erster Stelle ins
Struct legen, die ToString-Funktion kann es dort rausholen), aber ich
denke man sieht, worum es geht. Zeiger auf Funktionen ist das Stichwort.
Jedenfalls muß der Code im oberen Abschnitt nicht mehr zugàngig sein, um
einen eigenen Typ damit nutzen zu können (von den hier verwendeten
statischen Grenzen mal abgesehen).

Hoffe das hilft Dir weiter.

Gruß,
Felix

Ähnliche fragen