C – Fonction à l’intérieur de la structure

Im essayant de créer une fonction dans une structure, jusqu’à présent, j’ai ce code:

typedef struct client_t client_t, *pno; struct client_t { pid_t pid; char password[TAM_MAX]; // -> 50 chars pno next; pno AddClient() { /* code */ } }; int main() { client_t client; //code .. client.AddClient(); } 

Erreur : client.h: 24: 2: erreur: attendu ‘:’, ‘,’, ‘;’, ‘}’ ou ‘ atsortingbut ‘ avant ‘{‘ jeton.

Quelle est la bonne façon de le faire?

Cela ne peut pas être fait directement, mais vous pouvez émuler la même chose en utilisant des pointeurs de fonctions et en passant explicitement le paramètre “this”:

 typedef struct client_t client_t, *pno; struct client_t { pid_t pid; char password[TAM_MAX]; // -> 50 chars pno next; pno (*AddClient)(client_t *); }; pno client_t_AddClient(client_t *self) { /* code */ } int main() { client_t client; client.AddClient = client_t_AddClient; // probably really done in some init fn //code .. client.AddClient(&client); } 

Il s’avère que cela, cependant, ne vous achète pas vraiment beaucoup. En tant que tel, vous ne verrez pas beaucoup d’API C implémentées dans ce style, puisque vous pouvez tout aussi bien appeler votre fonction externe et passer l’instance.

Comme d’autres l’ont noté, l’intégration de pointeurs de fonction directement dans votre structure est généralement réservée à des fins spéciales, comme une fonction de rappel.

Ce que vous voulez probablement, c’est quelque chose qui ressemble plus à une table de méthode virtuelle.

 typedef struct client_ops_t client_ops_t; typedef struct client_t client_t, *pno; struct client_t { /* ... */ client_ops_t *ops; }; struct client_ops_t { pno (*AddClient)(client_t *); pno (*RemoveClient)(client_t *); }; pno AddClient (client_t *client) { return client->ops->AddClient(client); } pno RemoveClient (client_t *client) { return client->ops->RemoveClient(client); } 

Maintenant, l’ajout de nouvelles opérations ne modifie pas la taille de la structure client_t . Maintenant, ce type de flexibilité n’est utile que si vous devez définir de nombreux types de clients ou permettre aux utilisateurs de votre interface client_t d’augmenter le comportement des opérations.

Ce type de structure apparaît dans le code réel. La couche OpenSSL BIO ressemble à celle-ci et les interfaces de pilote de périphérique UNIX ont une couche comme celle-ci.

Cela ne fonctionnera qu’en C ++. Les fonctions dans les structures ne sont pas une caractéristique de C.

Idem pour votre client.AddClient (); call … c’est un appel pour une fonction membre, qui est la programmation orientée object, c.-à-d. C ++.

Convertissez votre source en fichier .cpp et assurez-vous de la comstackr en conséquence.

Si vous devez vous en tenir au C, le code ci-dessous est (en quelque sorte) l’équivalent:

 typedef struct client_t client_t, *pno; struct client_t { pid_t pid; char password[TAM_MAX]; // -> 50 chars pno next; }; pno AddClient(pno *pclient) { /* code */ } int main() { client_t client; //code .. AddClient(client); } 

Que dis-tu de ça?

 #include  typedef struct hello { int (*someFunction)(); } hello; int foo() { return 0; } hello Hello() { struct hello aHello; aHello.someFunction = &foo; return aHello; } int main() { struct hello aHello = Hello(); printf("Print hello: %d\n", aHello.someFunction()); return 0; } 

Vous essayez de regrouper le code en fonction de struct. Le regroupement C est par fichier. Vous mettez toutes les fonctions et les variables internes dans un en-tête ou un en-tête et un fichier object “.o” compilé à partir du fichier source ac.

Il n’est pas nécessaire de réinventer l’orientation object à partir d’un programme C, qui n’est pas un langage orienté object.

J’ai déjà vu ça avant. C’est une chose étrange. Les codeurs, certains d’entre eux, ont une aversion pour le passage d’un object qu’ils souhaitent transformer en une fonction pour le changer, même si c’est la méthode standard.

Je blâme C ++, car il cachait le fait que l’object de classe est toujours le premier paramètre dans une fonction membre, mais il est masqué. Il semble donc que l’object ne soit pas passé dans la fonction, même si c’est le cas.

 Client.addClient(Client& c); // addClient first parameter is actually // "this", a pointer to the Client object. 

C est flexible et peut prendre des choses en passant par référence.

La fonction AC retourne souvent uniquement un octet d’état ou int et est souvent ignoré. Dans votre cas, une forme appropriée pourrait être

  err = addClient( container_t cnt, client_t c); if ( err != 0 ) { fprintf(stderr, "could not add client (%d) \n", err ); 

addClient serait dans Client.h ou Client.c