Я пытаюсь создать функцию внутри структуры, пока у меня есть этот код:
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: ошибка: ожидается ':', ',', ';', '}' или ' attribute ' перед токеном '{'.
Как правильно это сделать?
Ответы:
Это невозможно сделать напрямую, но вы можете эмулировать то же самое, используя указатели на функции и явно передавая параметр 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); }
Однако оказывается, что это не очень много для вас. Таким образом, вы не увидите многих C API, реализованных в этом стиле, поскольку вы также можете просто вызвать свою внешнюю функцию и передать экземпляр.
источник
Как отмечали другие, встраивание указателей на функции непосредственно внутри вашей структуры обычно зарезервировано для специальных целей, таких как функция обратного вызова.
Вероятно, вам нужно нечто большее, чем таблица виртуальных методов.
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 имеют такой уровень.
источник
Это будет работать только в C ++. Функции в структурах не являются особенностями C.
То же самое и с вашим client.AddClient (); вызов ... это вызов функции-члена, которая является объектно-ориентированным программированием, то есть 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); }
источник
Как насчет этого?
#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; }
источник
Вы пытаетесь сгруппировать код в соответствии со структурой. C группировка по файлам. Вы помещаете все функции и внутренние переменные в заголовок или заголовок и объект ".o" файл, скомпилированный из исходного файла ac.
Нет необходимости заново изобретать объектную ориентацию с нуля для программы на C, которая не является объектно-ориентированным языком.
Я видел это раньше. Странная вещь. Кодеры, некоторые из них, не любят передавать объект, который они хотят изменить, в функцию для его изменения, хотя это стандартный способ сделать это.
Я виню C ++, потому что он скрывает тот факт, что объект класса всегда является первым параметром в функции-члене, но он скрыт. Итак, похоже, что он не передает объект в функцию, хотя это так.
Client.addClient(Client& c); // addClient first parameter is actually // "this", a pointer to the Client object.
C гибок и может передавать данные по ссылке.
Функция AC часто возвращает только байт состояния или целое число, которые часто игнорируются. В вашем случае правильная форма может быть
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
источник
do(object, subject)
), так и на OO (subject.do(object)
) стратегии упорядочивания функций, не означает, что мы должны прекратить пробовать это. Я полностью считаю правильным отметить, что это не исторический способ написания C, и что C не нужно писать таким образом (то же самое касается многих языков, особенно из процедурной, функциональной или логической парадигм), но мне не нужно активно препятствовать этому шаблону. У этого также есть некоторые преимуществаВы можете передать указатель структуры на функцию как аргумент функции. Это называется передачей по ссылке.
Если вы измените что-то внутри этого указателя, остальные будут обновлены до. Попробуйте вот так:
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 *client) { /* this will change the original client value */ client.password = "secret"; } int main() { client_t client; //code .. AddClient(&client); }
источник