Simulare i metodi
Fa parte della sezione Programmazione orientata agli oggetti del percorso C di Coddy. Lezione 39 di 61.
Hai visto come inserire un puntatore a funzione in una struct. Il vero potere emerge quando assegni funzioni diverse a istanze diverse dello stesso tipo di struct. È così che simuliamo metodi con comportamenti diversi.
Considera una struct che rappresenta un'azione con una logica personalizzabile:
typedef void (*ActionFunc)(void);
typedef struct {
const char* name;
ActionFunc execute;
} Action;Quando crei le istanze, colleghi funzioni diverse a ciascuna di esse:
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(); // Output: Hello!
farewell.execute(); // Output: Goodbye!
return 0;
}Sia greet che farewell sono dello stesso tipo (Action), eppure chiamare execute su ciascuno produce risultati completamente diversi. La struct non contiene solo dati: contiene un comportamento che varia a seconda dell'istanza.
Questo schema rispecchia il funzionamento degli oggetti in altri linguaggi: ogni oggetto può avere una propria implementazione di un metodo, anche se condividono la stessa interfaccia.
Sfida
FacileCostruiamo un sistema Speaker che dimostri come istanze diverse dello stesso tipo di struct possano manifestare comportamenti completamente diversi a seconda della funzione collegata a ciascuna di esse.
Creerai due file per organizzare il tuo codice:
speaker.h: Definisci un tipo puntatore a funzione chiamatoSpeakFuncche non accetta parametri e non restituisce nulla. Poi definisci una structSpeakercontenente unname(unconst char*) e un puntatore a funzionespeakdi tipoSpeakFunc.main.c: Includi il tuo header e implementa tre diverse funzioni per parlare:bark: stampaWoof!meow: stampaMeow!chirp: stampaChirp!
Speaker, ciascuna collegata a una funzione diversa in base all'input, e chiama i loro metodispeakper vedere il polimorfismo in azione.
Il tuo programma riceverà due input: il tipo del primo interlocutore (1 per bark, 2 per meow, 3 per chirp) e il tipo del secondo interlocutore (anch'esso 1, 2 o 3).
Crea due istanze di Speaker. Puoi chiamarle come preferisci (ad esempio "Dog", "Cat", "Bird" o semplicemente "Speaker1", "Speaker2"). Collega ciascuna alla funzione appropriata in base al suo codice di input, poi chiama speak su ogni istanza nell'ordine.
Esempio di output quando il primo tipo è 1 e il secondo tipo è 2:
Woof!
Meow!Esempio di output quando il primo tipo è 3 e il secondo tipo è 3:
Chirp!
Chirp!L'intuizione chiave è che entrambi gli interlocutori sono dello stesso tipo Speaker, eppure producono output diversi perché a ciascuno è assegnata una funzione diversa nel membro speak. Ricorda di usare le guardie di inclusione nel tuo file header.
Provalo tu
#include <stdio.h>
#include "speaker.h"
// TODO: Implementa la funzione bark che stampa "Woof!"
// TODO: Implementa la funzione meow che stampa "Meow!"
// TODO: Implementa la funzione chirp che stampa "Chirp!"
int main() {
int type1, type2;
scanf("%d", &type1);
scanf("%d", &type2);
// TODO: Crea due istanze di Speaker
// TODO: Collega la funzione speak del primo speaker in base a type1
// (1 = bark, 2 = meow, 3 = chirp)
// TODO: Collega la funzione speak del secondo speaker in base a type2
// (1 = bark, 2 = meow, 3 = chirp)
// TODO: Chiama speak su ciascuno speaker nell'ordine previsto
return 0;
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Basi di programmazione modulare
File di intestazioneGuardie di inclusioneFile sorgenteFunzioni staticheRipasso: calcolatrice modulare4Incapsulamento
Il concetto di puntatori opachiDefinire struct opacheGetter e setterLa convalida nei setterRiepilogo: scatola segreta2Oggetti e metodi
Le struct come oggettiIl puntatore 'Self'Correttezza constPuntatore o valoreMetodi di supportoRiepilogo: gestore di punti5Progetto: Conto bancario semplice
Configurazione del progettoImplementazione del conto8Polimorfismo
Puntatori a funzione nelle structSimulare i metodiIl concetto di interfacciaImplementare le interfacceIterazione polimorficaRiepilogo: Greeter11Pattern di progettazione in C
Pattern SingletonPattern FactoryPattern IteratorRiepilogo: Factory di Logger3Ciclo di vita degli oggetti
Pattern del costruttorePattern del distruttoreInizializzazione sullo stackCopia profondaRiepilogo: wrapper di stringhe6Ereditarietà tramite composizione
Incorporamento delle structLa regola del primo membroAccesso ai membri della classe baseUpcastingRiepilogo: gerarchia di forme9Progetto: Disegnatore di forme
Panoramica del progettoImplementazione del cerchioImplementazione del rettangoloUtilizzo polimorficoContenitore di formeEsercitati da solo: Compilatore C online