Projektübersicht
Teil des Abschnitts Object Oriented Programming der C-Journey von Coddy — Lektion 44 von 61.
Aufgabe
EinfachLegen wir den Grundstein für das Shape Drawer-Projekt, indem wir das Basis-Shape-Struct erstellen — ein Interface, das über Funktionszeiger definiert, was jede Form tun kann.
Sie werden zwei Dateien erstellen, um dieses polymorphe System einzurichten:
shape.h: Definieren Sie hier das Kern-Interface. Erstellen Sie zuerst eine Vorwärtsdeklaration für dasShape-Struct. Definieren Sie dann zwei Funktionszeigertypen:DrawFunc— erwartet einenconst Shape*Parameter und gibt nichts zurückAreaFunc— erwartet einenconst Shape*Parameter und gibt einendoublezurück
Shape-Struct selbst, das zwei Funktionszeiger enthält:draw(vom TypDrawFunc) undarea(vom TypAreaFunc). Dieses Struct fungiert rein als Interface — es enthält keine formspezifischen Daten, sondern nur Verhalten.main.c: Demonstrieren Sie, dass Ihr Interface funktioniert, indem Sie eine einfache Testform erstellen. Implementieren Sie zwei Funktionen:test_draw— gibtDrawing test shapeaustest_area— gibt42.0zurück
Shape-Instanz, verknüpfen Sie diese mit den Testfunktionen und rufen Sie dann beide über das Interface auf. Geben Sie das Flächenergebnis mit einer Nachkommastelle aus.
Ihre Ausgabe sollte zeigen, dass die Funktionszeiger korrekt funktionieren:
Drawing test shape
Area: 42.0Warum die Vorwärtsdeklaration? Sie fragen sich vielleicht, warum typedef struct Shape Shape; erscheint, bevor das Struct vollständig definiert ist. Dies ist notwendig, da DrawFunc und AreaFunc in ihren Parametertypen auf const Shape* verweisen — aber zu diesem Zeitpunkt in der Datei hat der Compiler die vollständige Struct-Definition noch nicht gesehen. Die Vorwärtsdeklaration sagt dem Compiler: "Ein Struct namens Shape existiert", was ausreicht, um einen Zeiger darauf zu verwenden. Die vollständige Definition folgt später. Dieses Muster ist in C üblich, wann immer ein Struct auf sich selbst verweisen muss (direkt oder über Funktionszeiger).
Die entscheidende Erkenntnis hier ist, dass Shape nichts über Kreise oder Rechtecke weiß — es weiß nur, dass jede Form in der Lage sein muss, sich selbst zu zeichnen (draw) und ihre Fläche (area) zu berechnen. In den kommenden Lektionen werden Sie konkrete Formen erstellen, die dieses Basis-Struct einbetten und ihre eigenen Implementierungen bereitstellen. Denken Sie daran, Include-Guards in Ihrer Header-Datei zu verwenden.
Probier es selbst
#include <stdio.h>
#include "shape.h"
// TODO: Implementiere die Funktion test_draw
// - Nimmt einen const Shape* Parameter entgegen
// - Gibt "Drawing test shape" aus
void test_draw(const Shape* shape) {
// TODO: Gib die erforderliche Nachricht aus
}
// TODO: Implementiere die Funktion test_area
// - Nimmt einen const Shape* Parameter entgegen
// - Gibt 42.0 zurück
double test_area(const Shape* shape) {
// TODO: Gib den Test-Flächenwert zurück
}
int main() {
// TODO: Erstelle eine Shape Instanz
// TODO: Verknüpfe das Shape mit den Funktionen test_draw und test_area
// TODO: Rufe draw über das Interface auf
// TODO: Rufe area über das Interface auf und gib es mit einer Dezimalstelle aus
// Format: "Area: %.1f\n"
return 0;
}
Alle Lektionen in Object Oriented Programming
1Grundlagen der modularen Programmierung
Header-DateienInclude GuardsQuelldateienStatische FunktionenWiederholung: Modularer Taschenrechner4Kapselung
Konzept der Opaque PointersOpaque Structs definierenGetter und SetterValidierung in SetternRückblick: Die geheime Box2Objekte und Methoden
Structs als ObjekteDer 'Self'-PointerConst-CorrectnessPointer vs. WertHilfsmethodenZusammenfassung: Point Manager5Projekt: Einfaches Bankkonto
Projekt-SetupImplementierung des Kontos3Objekt-Lebenszyklus
Konstruktor-MusterDestruktor-MusterStack-InitialisierungTiefe KopieRückblick: String-Wrapper6Vererbung durch Komposition
Struct-EinbettungDie First-Member-RegelZugriff auf Parent-MemberUpcastingRückblick: Formenhierarchie9Projekt: Formen-Zeichner
ProjektübersichtKreis-Implementierung