Подтвердить что ты не робот

C - функция внутри структуры

Я пытаюсь создать функцию внутри структуры, до сих пор у меня есть этот код:

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

}

Ошибка: client.h: 24: 2: ошибка: ожидается ':,', ';,'} или ' атрибут до' {токен.

Каков правильный способ сделать это?

4b9b3361

Ответ 1

Это невозможно сделать напрямую, но вы можете эмулировать одно и то же с помощью указателей функций и явно передавать параметр "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);

}

Оказывается, что делать это, однако, на самом деле не очень дорого стоит вам. Таким образом, вы не увидите много API C, реализованных в этом стиле, поскольку вы можете просто вызвать свою внешнюю функцию и передать экземпляр.

Ответ 2

Как отмечали другие, встроенные указатели на функции непосредственно внутри вашей структуры обычно зарезервированы для специальных целей, таких как функция обратного вызова.

То, что вы, вероятно, хотите, больше похоже на таблицу виртуальных методов.

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 имеют такой слой.

Ответ 3

Это будет работать только на С++. Функции в структурах не являются особенностью C.

То же самое касается вашего клиента .AddClient(); вызов... это вызов для функции-члена, которая является объектно-ориентированным программированием, то есть С++.

Преобразуйте исходный код в файл .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);

}

Ответ 4

Как насчет этого?

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

Ответ 5

Вы пытаетесь сгруппировать код в соответствии со структурой. Сгруппировка по файлу. Вы помещаете все функции и внутренние переменные в заголовок или заголовок и файл ".o" объекта, скомпилированный из исходного файла c.

Нет необходимости повторно изобретать объектную ориентацию с нуля для C-программы, которая не является объектно-ориентированным языком.

Я видел это раньше. Это странно. У некоторых кодеров есть отвращение к передаче объекта, который они хотят изменить, в функцию для его изменения, хотя это стандартный способ сделать это.

Я обвиняю С++, потому что скрывал тот факт, что объект класса всегда является первым параметром в функции-члене, но он скрыт. Таким образом, похоже, что он не передает объект в функцию, даже если он есть.

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

C является гибким и может принимать передаточные вещи по ссылке.

Функция C часто возвращает только статусный байт или int, и это часто игнорируется. В вашем случае правильная форма может быть

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

addClient будет в Client.h или Client.c