Funktionszeiger in Structs
Teil des Abschnitts Objektorientierte Programmierung der C-Journey von Coddy. Lektion 38 von 61.
Bisher haben wir Funktionszeiger als eigenständige Variablen verwendet oder sie als Argumente übergeben. Der nächste Schritt in Richtung Polymorphie besteht darin, einen Funktionszeiger direkt in eine Struktur einzubetten und der Struktur dadurch ihr eigenes Verhalten zu geben.
Wenn eine Struktur einen Funktionszeiger enthält, kann jede Instanz eine andere Funktion enthalten. Das bedeutet, dass sich zwei Objekte desselben Typs unterschiedlich verhalten können, wenn du ihren Funktionszeiger aufrufst:
typedef void (*PrintFunc)(const char*);
typedef struct {
const char* name;
PrintFunc print; // Funktionszeiger als Member
} Printer;Die Struktur Printer hat jetzt zwei member: Daten (name) und Verhalten (print). Um sie zu verwenden, weist du dem pointer während der Initialisierung eine Funktion zu:
void loud_print(const char* msg) {
printf("!!! %s !!!\n", msg);
}
int main() {
Printer p;
p.name = "Alert";
p.print = loud_print;
p.print("Hello"); // Ausgabe: !!! Hello !!!
return 0;
}Beachte, wie wir die Funktion über die Struktur aufrufen: p.print("Hello"). Das sieht bemerkenswert ähnlich aus wie der Aufruf einer Methode auf einem Objekt in anderen Sprachen. Die Struktur enthält sowohl ihre Daten als auch die Funktion, die auf ihnen operiert.
Dieses Muster bildet die Grundlage des Polymorphismus in C: Verschiedenen Instanzen können unterschiedliche Funktionen zugewiesen werden, wodurch sich aus demselben Strukturtyp unterschiedliche Verhaltensweisen ergeben.
Aufgabe
EinfachErstelle ein Notifier-System, das demonstriert, wie Structs ihr eigenes Verhalten mithilfe von Funktionszeigern enthalten können.
Du erstellst zwei Dateien, um deinen Code zu organisieren:
notifier.h: Definiere einen Funktionszeigertyp namensNotifyFunc, der einenconst char*-Parameter entgegennimmt und nichts zurückgibt. Definiere anschließend einNotifier-Struct, das einenname(einenconst char*) und einennotify-Funktionszeiger vom TypNotifyFuncenthält.main.c: Binde deinen Header ein und implementiere zwei Benachrichtigungsfunktionen:alert_notify: Gibt die Nachricht im Format[ALERT] messageaus.info_notify: Gibt die Nachricht im Format[INFO] messageaus.
Notifier-Instanz, verknüpfe abhängig von der Eingabe die passende Funktion und rufe die Benachrichtigung über den Funktionszeiger des Structs auf.
Dein Programm erhält zwei Eingaben: einen Benachrichtigungstyp (1 für Alarm, 2 für Information) und eine anzuzeigende Nachricht.
Weise abhängig vom Typ die entsprechende Funktion dem Member notify deines Notifiers zu und rufe sie anschließend über das Struct auf, um die Nachricht anzuzeigen.
Beispielausgabe, wenn der Typ 1 und die Nachricht "System starting" ist:
[ALERT] System startingBeispielausgabe, wenn der Typ 2 und die Nachricht "All systems normal" ist:
[INFO] All systems normalDenke daran, Include-Guards in deiner Header-Datei zu verwenden und die Funktion über den Struct-Member aufzurufen: n.notify(message)
Probier es selbst
#include <stdio.h>
#include "notifier.h"
// TODO: Implementiere die Funktion alert_notify
// Sollte ausgeben: [ALERT] message
// TODO: Implementiere die Funktion info_notify
// Sollte ausgeben: [INFO] message
int main() {
int type;
char message[256];
// Eingabe lesen
scanf("%d", &type);
getchar(); // Zeilenumbruch konsumieren
fgets(message, sizeof(message), stdin);
// Abschließenden Zeilenumbruch aus message entfernen, falls vorhanden
int len = 0;
while (message[len] != '\0') len++;
if (len > 0 && message[len-1] == '\n') message[len-1] = '\0';
// TODO: Erstelle eine Notifier-Instanz
// TODO: Basierend auf type (1 für alert, 2 für info),
// weise die entsprechende Funktion dem notify-Member des Notifiers zu
// TODO: Rufe die Benachrichtigung über den Funktionszeiger des Structs auf
// Verwende: n.notify(message)
return 0;
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
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 Kontos8Polymorphismus
Funktionszeiger in StructsMethoden simulierenDas Interface-KonzeptInterfaces implementierenPolymorphe IterationWiederholung: Greeter3Objekt-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-ImplementierungRechteck-ImplementierungPolymorphe VerwendungShape-ContainerÜbe selbstständig: Online-C-Compiler