Ich versuche eine Funktion innerhalb einer Struktur zu erstellen, bis jetzt habe ich diesen 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();
}
Fehler : client.h: 24: 2: Fehler: erwartet ':', ',', ';', '}' oder ' Attribut ' vor '{' Token.
Welches ist der richtige Weg, um es zu tun?
Antworten:
Dies kann nicht direkt durchgeführt werden, aber Sie können dasselbe mithilfe von Funktionszeigern emulieren und den Parameter "this" explizit übergeben:
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); }
Es stellt sich jedoch heraus, dass Sie dadurch nicht wirklich viel kaufen. Daher werden nicht viele C-APIs in diesem Stil implementiert, da Sie auch einfach Ihre externe Funktion aufrufen und die Instanz übergeben können.
quelle
Wie andere angemerkt haben, ist das Einbetten von Funktionszeigern direkt in Ihre Struktur normalerweise für spezielle Zwecke reserviert, z. B. für eine Rückruffunktion.
Was Sie wahrscheinlich wollen, ist eher eine virtuelle Methodentabelle.
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); }
Das Hinzufügen weiterer Operationen ändert nun nichts an der Größe der
client_t
Struktur. Diese Art der Flexibilität ist nur dann nützlich, wenn Sie viele Arten von Clients definieren müssen oder Benutzern Ihrerclient_t
Benutzeroberfläche ermöglichen möchten, das Verhalten der Vorgänge zu verbessern.Diese Art von Struktur erscheint in echtem Code. Die OpenSSL-BIO-Schicht sieht ähnlich aus, und auch UNIX-Gerätetreiberschnittstellen haben eine solche Schicht.
quelle
Dies funktioniert nur in C ++. Funktionen in Strukturen sind kein Merkmal von C.
Gleiches gilt für Ihren Client.AddClient (); call ... Dies ist ein Aufruf für eine Member-Funktion, bei der es sich um objektorientierte Programmierung handelt, dh C ++.
Konvertieren Sie Ihre Quelle in eine CPP-Datei und stellen Sie sicher, dass Sie entsprechend kompilieren.
Wenn Sie sich an C halten müssen, ist der folgende Code (irgendwie) das Ä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); }
quelle
Wie wäre es damit?
#include <stdio.h> 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; }
quelle
Sie versuchen, Code nach Struktur zu gruppieren. Die C-Gruppierung erfolgt nach Datei. Sie fügen alle Funktionen und internen Variablen in einen Header oder einen Header und eine aus einer AC-Quelldatei kompilierte Objektdatei ".o" ein.
Für ein C-Programm, das keine objektorientierte Sprache ist, ist es nicht erforderlich, die Objektorientierung von Grund auf neu zu erfinden.
Ich habe das schon mal gesehen. Es ist eine seltsame Sache. Einige von ihnen haben eine Abneigung dagegen, ein Objekt, das sie ändern möchten, in eine Funktion zu übergeben, um es zu ändern, obwohl dies die Standardmethode ist.
Ich beschuldige C ++, weil es die Tatsache verborgen hat, dass das Klassenobjekt immer der erste Parameter in einer Mitgliedsfunktion ist, aber es ist versteckt. Es sieht also so aus, als würde das Objekt nicht an die Funktion übergeben, obwohl dies der Fall ist.
Client.addClient(Client& c); // addClient first parameter is actually // "this", a pointer to the Client object.
C ist flexibel und kann vorübergehende Dinge als Referenz nehmen.
Die AC-Funktion gibt häufig nur ein Statusbyte oder int zurück und wird häufig ignoriert. In Ihrem Fall könnte eine richtige Form sein
err = addClient( container_t cnt, client_t c); if ( err != 0 ) { fprintf(stderr, "could not add client (%d) \n", err );
addClient wäre in Client.h oder Client.c
quelle
do(object, subject)
) - als auch auf die OO (subject.do(object)
) -Strategie zum Anordnen von Funktionen bezieht, heißt das nicht, dass wir aufhören sollten, es auszuprobieren. Ich denke , dass es total gültig ist dies darauf hinzuweisen, ist nicht der historische Weg C geschrieben wurde, und dass C nicht braucht diese Art und Weise geschrieben werden ( das gleiche gilt für viele Sprachen, besonders thoes aus prozedurale, funktionalen oder logischen Paradigmen), aber ich nicht, wir müssen das Muster aktiv entmutigen. Es hat auch einige Vorteile