Polymorphismus endlich auch in C

Neidisch und voller Bewunderung schauen C-Programmierer auf ihre objektorientierungsvirtuosen Kollegen, die sich in der Firma wie Götter gebärden. Warum nur hat der Chef C angeordnet? C-Programmierer wollen auch diese tollen Sachen machen und bewundert werden. Aber was ist das überhaupt, was die da machen?

Was ist diese Objektorientierung überhaupt?

Bei der Objektorientierung geht es darum, die Trennung zwischen statischer Struktur und Verhalten aufzubrechen. Wo in C noch Structs von Funktionen beackert wurden, kommen in C++ jetzt die Structs als „Klassen“ daher und bringen ihren Code gleich noch mit – ein mittlerer Alptraum für jeden Architekten, der Struktur und Verhalten lieber getrennt sehen möchte. Ein paar fiese Konzepte besiegeln dazu die restlose Verwirrung. Anders als in C kann eine Funktion (die jetzt „Methode“ heißt“) je nach Parametertyp unterschiedliche Implementierungen mitbringen:

float calculateArea(Rectangle* r) {/*…*/}
float calculateArea(Triangle* t) {/*…*/}

In C++ ist die Einschränkung also nicht mehr gegeben, dass es für einen Funktionsnamen genau einen Parametertyp geben muss.

Was da in Wirklichkeit passiert – die ungeschönte Wahrheit

Compiler für C++ verstehen Objektorientierung genauso wenig wie die meisten Entwickler. Klar, es gibt viele tolle Bücher über Objektorientierung. Hier seien Effective C++ von Scott Meyers oder Design Patterns von Erich Gamma et al. genannt, nur als Beispiel. Ziemlich schwer zu verstehen, und bisher ist auch nicht erwiesen, dass die dort skizzierten Kunststückchen wirklich der Quantensprung in der Informatik sind. Wir haben in unserem Labor keine Mühen gescheut und mal unter die Haube des Compilers geschaut, was der Compiler so genau anstellt, wenn er so ein Stück Objektorientierung bekommt. Hier ein Beispiel:

float Calculator::calculateArea(Triangle* t) {/*…*/}
float Calculator::calculateArea(Rectangle* t) {/*…*/}

Einen Compilerlauf später erhalten wir daraus

        .globl  _ZN10Calculator13calculateAreaEP8Triangle
        .type   _ZN10Calculator13calculateAreaEP8Triangle, @function
_ZN10Calculator13calculateAreaEP8Triangle:
.LFB0:
        pushq   %rbp
[…]

Auffällig dabei ist, dass die eigentlichen Klassen- und Methodennamen nicht mehr direkt erkenntlich sind, sondern kryptisch eingepackt wurden. Ist Objektorientierung nur ein Trend, hinter dem funktionale Programmierung steckt? Diese Verschlüsselung der Methodennamen auf Assembler-Ebene zeigt sehr deutlich, dass am Ende diese ganze Objektorientierung in Prinzipien der funktionalen Programmierung übersetzt wird. Die zugehörige Fachvokabel heißt „Name-Mangling“ und ist hier am Beispiel GCC gezeigt. Doch warum muss das ganze so kompliziert verschlüsselt werden? Wäre es nicht viel einfacher und auch lesbarer, wenn man die Verschlüsselung weniger krass anwendet? Und: Wenn das sowieso in ein funktionales Konzept übersetzt wird, warum soll dann z.B. die oben benannte Polymorphie nicht auch in C funktionieren?

Geht das dann auch in C?

Ja! Das geht! Zwar etwas eingeschränkt, da man nicht alles in dieser automatisierten Übersetzung von Hand implementieren will, aber einige Aspekte lassen sich mit ganz wenig Aufwand auch nach C übertragen, so auch Polymorphie. Für oben genanntes Problem nutzen wir also Methodennamen, die sich möglichst ähnlich sehen. Seit einiger Zeit unterstützen die meisten Compiler Unicode im Programmier-Quellcode, so dass wir auch auf andere Alphabete mit beinahe gleich aussehenden Buchstaben zurückgreifen können. Hier im Beispiel nutzen wir das kyrillische ‚г‘, um dem lateinischen ‚r‘ möglichst nahe zu kommen. Falls man im kyrillischen Alphabet nicht fündig wird, helfen vielleicht das griechische Alphabet oder die vielen verschiedenen Schriften aus Asien.

float calculateArea(Triangle t) {/*...*/}
float calculateAгea(Rectagle r) {/*...*/}

Auch IDEs unterstützen den Entwickler bei diesem Ansatz:

IDE Support

Fazit

Nachdem die Compiler-Entwickler in den gebräuchlichen Compilern ohnehin schon tricksen, was das Zeug hält, ist es absolut legitim, sich diese Tricks bewusst zum Vorteil zu machen. Insbesondere, wenn es darum geht, sich der Einschränkungen der Programmiersprache C zu entledigen hilft der bewusste Einsatz von Unicode ungemein.