114

内に関数を割り当てようとしていますがstruct、これまでのところ、次のコードがあります。

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 ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘{’ token.*

それを行う正しい方法はどれですか?

4

6 に答える 6

32

他の人が指摘したように、関数ポインターを構造内に直接埋め込むことは、通常、コールバック関数などの特別な目的のために予約されています。

おそらく必要なのは、仮想メソッド テーブルのようなものです。

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

現在、操作を追加してもclient_t構造体のサイズは変わりません。現在、この種の柔軟性は、多くの種類のクライアントを定義する必要がある場合、またはインターフェイスのユーザーがclient_t操作の動作を拡張できるようにする場合にのみ役立ちます。

この種の構造は、実際のコードに表示されます。OpenSSL の BIO レイヤーはこれに似ていますが、UNIX デバイス ドライバー インターフェイスにもこのようなレイヤーがあります。

于 2013-06-11T21:01:40.790 に答える
22

これはどう?

#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;
} 
于 2015-10-06T07:55:13.573 に答える
14

これは C++ でのみ機能します。構造体の関数は C の機能ではありません。

client.AddClient(); についても同じことが言えます。call ... これは、オブジェクト指向プログラミング、つまり C++ であるメンバー関数の呼び出しです。

ソースを .cpp ファイルに変換し、それに応じてコンパイルしていることを確認してください。

Cに固執する必要がある場合、以下のコードは(一種の)同等のものです:

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

}
于 2013-06-11T19:47:34.733 に答える