Simulation de méthodes
Fait partie de la section Object Oriented Programming du Journey C de Coddy — leçon 39 sur 61.
Vous avez vu comment placer un pointeur de fonction à l'intérieur d'une struct. La véritable puissance apparaît lorsque vous assignez différentes fonctions à différentes instances du même type de struct — c'est ainsi que nous simulons des méthodes avec des comportements variés.
Considérez une structure qui représente une action avec une logique personnalisable :
typedef void (*ActionFunc)(void);
typedef struct {
const char* name;
ActionFunc execute;
} Action;Lors de la création d'instances, vous reliez différentes fonctions à chacune d'elles :
void say_hello(void) {
printf("Hello!\n");
}
void say_goodbye(void) {
printf("Goodbye!\n");
}
int main() {
Action greet = { "Greet", say_hello };
Action farewell = { "Farewell", say_goodbye };
greet.execute(); // Sortie : Hello!
farewell.execute(); // Sortie : Goodbye!
return 0;
}À la fois greet et farewell sont du même type (Action), pourtant appeler execute sur chacun produit des résultats complètement différents. La structure ne contient pas seulement des données — elle contient un comportement qui varie selon l'instance.
Ce modèle reflète la manière dont les objets fonctionnent dans d'autres langages : chaque objet peut avoir sa propre implémentation d'une méthode, même s'ils partagent la même interface.
Défi
FacileConstruisons un système Speaker qui démontre comment différentes instances du même type de structure peuvent présenter des comportements complètement différents selon la fonction qui leur est associée.
Vous allez créer deux fichiers pour organiser votre code :
speaker.h: Définissez un type de pointeur de fonction appeléSpeakFuncqui ne prend aucun paramètre et ne renvoie rien. Ensuite, définissez une structureSpeakercontenant unname(unconst char*) et un pointeur de fonctionspeakde typeSpeakFunc.main.c: Incluez votre en-tête et implémentez trois fonctions de parole différentes :bark— afficheWoof!meow— afficheMeow!chirp— afficheChirp!
Speaker, chacune reliée à une fonction différente en fonction de l'entrée, et appelez leurs méthodesspeakpour voir le comportement polymorphe en action.
Votre programme recevra deux entrées : le premier type de haut-parleur (1 pour bark, 2 pour meow, 3 pour chirp) et le second type de haut-parleur (également 1, 2 ou 3).
Créez deux instances de Speaker — vous pouvez les nommer comme vous le souhaitez (comme "Dog", "Cat", "Bird", ou simplement "Speaker1", "Speaker2"). Reliez chacune d'elles à la fonction appropriée en fonction de son code d'entrée, puis appelez speak sur chaque instance dans l'ordre.
Exemple de sortie lorsque le premier type est 1 et le second type est 2 :
Woof!
Meow!Exemple de sortie lorsque le premier type est 3 et le second type est 3 :
Chirp!
Chirp!L'idée clé ici est que les deux haut-parleurs sont du même type Speaker, mais ils produisent des sorties différentes car chacun a une fonction différente assignée à son membre speak. N'oubliez pas d'utiliser des gardes d'inclusion dans votre fichier d'en-tête.
Aide-mémoire
Différentes instances du même type de structure peuvent contenir différents pointeurs de fonction, permettant un comportement polymorphe.
Définissez un type de pointeur de fonction et une structure qui l'utilise :
typedef void (*ActionFunc)(void);
typedef struct {
const char* name;
ActionFunc execute;
} Action;Créez des instances avec différentes fonctions assignées :
void say_hello(void) {
printf("Hello!\n");
}
void say_goodbye(void) {
printf("Goodbye!\n");
}
int main() {
Action greet = { "Greet", say_hello };
Action farewell = { "Farewell", say_goodbye };
greet.execute(); // Résultat : Hello!
farewell.execute(); // Résultat : Goodbye!
return 0;
}Les deux instances partagent le même type mais présentent un comportement différent lorsque leurs pointeurs de fonction sont appelés.
Essayez vous-même
#include <stdio.h>
#include "speaker.h"
// TODO: Implémenter la fonction bark qui affiche "Woof!"
// TODO: Implémenter la fonction meow qui affiche "Meow!"
// TODO: Implémenter la fonction chirp qui affiche "Chirp!"
int main() {
int type1, type2;
scanf("%d", &type1);
scanf("%d", &type2);
// TODO: Créer deux instances de Speaker
// TODO: Relier la fonction speak du premier haut-parleur en fonction de type1
// (1 = bark, 2 = meow, 3 = chirp)
// TODO: Relier la fonction speak du deuxième haut-parleur en fonction de type2
// (1 = bark, 2 = meow, 3 = chirp)
// TODO: Appeler speak sur chaque haut-parleur dans l'ordre
return 0;
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Object Oriented Programming
1Bases de la programmation modulaire
Fichiers d'en-têteGardes d'inclusionFichiers sourcesFonctions statiquesRécapitulatif : Calculatrice modulaire4Encapsulation
Concept des pointeurs opaquesDéfinir des structures opaquesGetters et settersValidation dans les settersRécapitulatif : La boîte secrète2Objets et méthodes
Structs comme objetsLe pointeur 'Self'Rigueur du mot-clé constPointeur vs ValeurMéthodes utilitairesRécapitulatif : Point Manager5Projet : Compte bancaire simple
Configuration du projetImplémentation du compte8Polymorphisme
Pointeurs de fonctions dans les structuresSimulation de méthodesLe concept d'interfaceImplémentation d'interfacesItération polymorphiqueRécapitulatif : Greeter11Patrons de conception en C
Patron SingletonPatron FabriquePatron ItérateurRécapitulatif : Logger Factory3Cycle de vie des objets
Pattern de constructeurPattern de destructeurInitialisation sur la pileCopie profondeRécapitulatif : String Wrapper6Héritage par composition
Imbrication de structLa règle du premier membreAccès aux membres parentsUpcastingRécapitulatif : Hiérarchie des formes9Projet : Dessinateur de formes
Aperçu du projetImplémentation du cercle