C – función dentro de struct

Estoy tratando de crear una función dentro de una estructura, hasta ahora tengo este código:

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(); } 

Error : client.h: 24: 2: error: expected ‘:’, ‘,’, ‘;’, ‘}’ o ‘ attribute ‘ antes del token ‘{‘.

¿Cuál es la forma correcta de hacerlo?

No se puede hacer directamente, pero puede emular lo mismo usando punteros a funciones y pasando explícitamente el parámetro “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); } 

Resulta que hacer esto, sin embargo, realmente no te compra mucho. Como tal, no verá muchas API C implementadas en este estilo, ya que también puede llamar a su función externa y pasar la instancia.

Como otros han notado, insertar punteros de función directamente dentro de su estructura generalmente se reserva para propósitos especiales, como una función de callback.

Lo que probablemente desee es algo más parecido a una tabla de métodos virtuales.

 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); } 

Ahora, agregar más operaciones no cambia el tamaño de la estructura client_t . Ahora, este tipo de flexibilidad solo es útil si necesita definir muchos tipos de clientes o si desea permitir que los usuarios de su interfaz client_t puedan boost el comportamiento de las operaciones.

Este tipo de estructura aparece en código real. La capa OpenSSL BIO es similar a esto, y también las interfaces del controlador de dispositivo UNIX tienen una capa como esta.

Esto solo funcionará en C ++. Las funciones en las estructuras no son una característica de C.

Lo mismo aplica para su cliente.AddClient (); llame … esta es una llamada para una función miembro, que es progtwigción orientada a objetos, es decir, C ++.

Convierta su fuente a un archivo .cpp y asegúrese de que está comstackndo en consecuencia.

Si necesita apegarse a C, el siguiente código es (más o menos) el equivalente:

 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); } 

¿Qué tal esto?

 #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; } 

Está intentando agrupar código de acuerdo con struct. La agrupación C es por archivo. Coloca todas las funciones y variables internas en un encabezado o encabezado y un archivo de objeto “.o” comstackdo a partir de un archivo de código fuente.

No es necesario reinventar la orientación a objetos desde cero para un progtwig C, que no es un lenguaje orientado a objetos.

He visto esto antes. Es algo extraño. Los codificadores, algunos de ellos, tienen una aversión a pasar un objeto que quieren cambiar a una función para cambiarlo, aunque esa es la forma estándar de hacerlo.

Culpo a C ++, porque ocultaba el hecho de que el objeto de clase siempre es el primer parámetro en una función miembro, pero está oculto. Por lo tanto, parece que no está pasando el objeto a la función, aunque lo esté.

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

C es flexible y puede tomar cosas por referencia.

La función de CA a menudo solo devuelve un byte de estado o int y a menudo se ignora. En su caso, una forma adecuada podría ser

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

addClient estaría en Client.h o Client.c