Konstruktor-Muster
Teil des Abschnitts Object Oriented Programming der C-Journey von Coddy — Lektion 12 von 61.
In Sprachen wie Java oder C++ erstellen Sie Objekte mithilfe von Konstruktoren – speziellen Funktionen, die automatisch Speicher zuweisen und Felder initialisieren. C verfügt über keine solche Funktion, aber wir können sie mit einem einfachen Muster simulieren: einer create_-Funktion.
Eine Konstruktor-Funktion in C macht normalerweise drei Dinge: sie reserviert Speicher mit malloc, initialisiert alle Felder mit den richtigen Werten und gibt einen Zeiger auf das neue Objekt zurück:
typedef struct {
char *name;
int age;
} Person;
Person *create_person(const char *name, int age) {
Person *p = malloc(sizeof(Person));
p->name = malloc(strlen(name) + 1);
strcpy(p->name, name);
p->age = age;
return p;
}
Die Funktion gibt einen Zeiger zurück, da das Objekt auf dem Heap und nicht auf dem Stack liegt. Das bedeutet, dass es nach der Rückgabe der Funktion bestehen bleibt und frei weitergegeben werden kann. Der Aufrufer verwendet es so:
Person *alice = create_person("Alice", 30);
printf("%s is %d years old\n", alice->name, alice->age);
Beachten Sie, wie der Konstruktor all die mühsamen Details übernimmt – das Allokieren des Structs, das Reservieren von Speicherplatz für den String und das Kopieren der Daten. Der Aufrufer stellt lediglich die Initialwerte bereit und erhält ein einsatzbereites Objekt. Dies kapselt die Erstellungslogik an einem Ort, was Ihren Code sauberer und weniger fehleranfällig macht.
Aufgabe
EinfachLassen Sie uns ein Book-Modul erstellen, das das Constructor-Pattern verwendet, um Buch-Objekte auf dem Heap zu erzeugen. Sie werden üben, eine create_-Funktion zu schreiben, die die gesamte Speicherallokation und Initialisierung übernimmt und einen einsatzbereiten Pointer zurückgibt.
Sie werden drei Dateien erstellen:
book.h: Deklarieren Sie einBook-Struct mit zwei Elementen:char *title(ein Pointer auf einen dynamisch allokierten String) undint pages. Deklarieren Sie außerdem eine Constructor-Funktioncreate_book, die einen Titel-String und die Seitenanzahl entgegennimmt und einen Pointer auf ein neu erstelltes Book zurückgibt. Verwenden Sie Include-Guards mit dem SymbolBOOK_H.book.c: Implementieren Sie die Funktioncreate_book. Ihr Constructor sollte Speicher für das Book-Struct selbst allokieren, dann separaten Speicher für den Titel-String allokieren (denken Sie daran, den Null-Terminator zu berücksichtigen), den Titel in den neuen Speicher kopieren, das Feld pages setzen und den Pointer auf das neue Book zurückgeben.main.c: Verwenden Sie Ihren Constructor, um ein Buch zu erstellen und dessen Informationen anzuzeigen.
Sie erhalten zwei Eingaben: den book title (einen String) und die number of pages (einen Integer).
Verwenden Sie in Ihrer Hauptdatei create_book, um ein neues Buch mit den angegebenen Werten zu erstellen, und geben Sie die Informationen in diesem Format aus:
Title: {title}
Pages: {pages}Zum Beispiel wäre bei den Eingaben The C Programming Language und 272 die Ausgabe:
Title: The C Programming Language
Pages: 272Denken Sie daran, dass Ihr Constructor die gesamte Erstellungslogik kapselt – der Aufrufer stellt lediglich die Initialwerte bereit und erhält ein vollständig initialisiertes, einsatzbereites Objekt zurück.
Spickzettel
Eine Konstruktor-Funktion in C simuliert die Objekterzeugung durch Speicherallokation und Initialisierung von Feldern. Sie folgt typischerweise dem create_-Namensschema.
Eine Konstruktor-Funktion erledigt drei Dinge:
- Allokiert Speicher mit
malloc - Initialisiert alle Felder mit den entsprechenden Werten
- Gibt einen Pointer auf das neue Objekt zurück
Beispiel für ein Konstruktor-Muster:
typedef struct {
char *name;
int age;
} Person;
Person *create_person(const char *name, int age) {
Person *p = malloc(sizeof(Person));
p->name = malloc(strlen(name) + 1);
strcpy(p->name, name);
p->age = age;
return p;
}
Verwendung des Konstruktors:
Person *alice = create_person("Alice", 30);
printf("%s is %d years old\n", alice->name, alice->age);
Die Funktion gibt einen Pointer zurück, da das Objekt auf dem Heap liegt und nach dem Beenden der Funktion bestehen bleibt. Dies kapselt die Erzeugungslogik an einer Stelle, was den Code sauberer und weniger fehleranfällig macht.
Probier es selbst
#include <stdio.h>
#include <stdlib.h>
#include "book.h"
int main() {
char title[256];
int pages;
// Eingabe lesen
fgets(title, sizeof(title), stdin);
// Zeilenumbruch entfernen, falls vorhanden
for (int i = 0; title[i]; i++) {
if (title[i] == '\n') {
title[i] = '\0';
break;
}
}
scanf("%d", &pages);
// TODO: Verwende create_book, um ein neues Buch mit den angegebenen Werten zu erstellen
// TODO: Gib die Buchinformationen im erforderlichen Format aus:
// Title: {title}
// Pages: {pages}
// TODO: Vergiss nicht, den zugewiesenen Speicher freizugeben, wenn du fertig bist
return 0;
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
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