Può una struttura C comportarsi come se avesse una funzione?

13

Uso C e struct s dove una struct può avere membri ma non funzioni. Supponiamo per semplicità che voglio creare una struct per le stringhe che chiamo str e voglio essere in grado di fare str.replace(int i, char c) dove i è l'indice della stringa e c è il carattere per sostituire il carattere alla posizione i . Non sarebbe mai possibile, dal momento che le strutture non possono avere funzioni o c'è ancora un modo per implementare questo comportamento e imitare che una struct possa avere una (semplice) funzione che in realtà è solo la struct che si copia su una nuova struttura e che aggiorna la sua campi, che potrebbe fare?

Quindi replace potrebbe essere un terzo membro della struttura che punta a una nuova struttura che viene aggiornata quando viene acceduta o simile. Potrebbe essere fatto? O c'è qualcosa di costruito o qualche teoria o paradigma che impedisce la mia intenzione?

Lo sfondo è che sto scrivendo codice C e mi ritrovo a reinventare funzioni che so essere incorporate nella libreria nei linguaggi OOP e che OOP sarebbe un buon modo per manipolare stringhe e comandi.

    
posta Niklas Rosencrantz 25.05.2016 - 05:33
fonte

4 risposte

21

La tua funzione dovrebbe apparire così.

void
replace(struct string * s, int i, char c);

Questo accetta un puntatore all'oggetto su cui operare come primo parametro. In C ++, questo è noto come this -pointer e non è necessario dichiararlo esplicitamente. (Confrontalo con Python dove deve.)

Per chiamare la tua funzione, dovresti anche passare esplicitamente quel puntatore. Fondamentalmente, scambi la sintassi o.f(…) per la sintassi f(&o, …) . Non è un grosso problema.

La storia diventa più coinvolgente se vuoi supportare il polimorfismo (ovvero% funzioni% di%). Può anche essere emulato in C (l'ho mostrato per questa risposta .) Ma non è bello da fare a mano.

Poiché Jan Hudec ha commentato, dovresti anche prendere l'abitudine di precedere il nome della funzione con il nome del tipo (cioè virtual ) perché C non ha spazi dei nomi, quindi può esserci solo una singola funzione chiamata string_replace .

    
risposta data 25.05.2016 - 05:46
fonte
42

Le strutture possono contenere la funzione puntatori , ma quelle sono davvero necessarie solo per i metodi virtuali. I metodi non virtuali in C orientata agli oggetti vengono solitamente eseguiti passando la struct come primo argomento a una funzione regolare. Esamina Gobject per un buon esempio di un framework OOP per C. Utilizza macro per gestire gran parte del boilerplate richiesto per l'ereditarietà e polimorfismo.

C è stato creato 44 anni fa. È una lingua molto popolare per l'open source. Non sei la prima persona a pensare che le stringhe C standard siano goffe con cui lavorare. Effettua alcune ricerche per le librerie di stringhe C. Non devi reinventare la ruota.

    
risposta data 25.05.2016 - 06:13
fonte
8

Con i puntatori di funzione, puoi fare:

str.replace(&str, i, c);

Questo è generalmente utile solo se l'implementazione può cambiare, nel qual caso dovresti usare un vtable in modo che l'overhead sia solo un puntatore per struct:

str.vtable->replace(&str, i, c);
    
risposta data 25.05.2016 - 05:43
fonte
3

Sì, possono, un po '. Si può fare uso del fatto che C consente ai puntatori di funzionare in memoria, puntatori di funzioni a.k.a. e che si può creare un'interfaccia come il polimorfismo così come le funzioni virtuali (anche se non è così bello).

Ho scritto un post su questo argomento, a seguito di una domanda di uno dei miei studenti, recente, relativa al codice simile all'interfaccia in C e Go, puoi leggerla qui:

Post del blog su interfacce non OO

Vedi se ti dà qualche idea.

Potresti anche inserire una funzione gratuita nel tuo codice e usare un "questo" -pointer, cioè passare un puntatore a una struttura esistente su cui lavorare, come descritto in altre risposte.

    
risposta data 25.05.2016 - 12:47
fonte

Leggi altre domande sui tag