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


86

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

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

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


12
У вас не может быть функций в структурах в C; вы можете попытаться примерно смоделировать это с помощью указателей функций.
Fingolfin

1
Являются ли указатели на функции приемлемой заменой? stackoverflow.com/a/840703/635678
Дэн О

Ответы:


108

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

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


3
X11 API делает что-то вроде этого. См. XImage .
Hydranix 08

1
код, который находится под Windows API, полон этого. Технически «оконный класс» - это структура с двумя указателями на функцию обратного вызова и с открытым концом (для этих «данных о классе окна», которые вы можете указать при регистрации)
Swift - Friday Pie

1
выполнил эти шаги, но когда я делаю struct.function = newFunction, компилятор print: error: expected '=', ',', ';', 'asm' или ' attribute ' before '.' токен
Bonfra

Это также будет полезно, когда вам нужна общая цель (например, жесткий диск), которая имеет функцию чтения и функцию записи, но которая варьируется от одного типа жесткого диска до nexf
Menotdan

Это может принести вам много денег, если фактическая реализация будет выбрана во время выполнения. Если у вас есть только статическая функция, вам всегда нужно повторно выбирать в этой функции при каждом вызове функции, если вы используете указатель функции, выбор происходит только один раз. И выбор может даже меняться в течение всего срока службы структуры.
Mecki

24

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

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

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

Такая структура действительно присутствует в реальном коде. Уровень OpenSSL BIO выглядит аналогично этому, а также интерфейсы драйверов устройств UNIX имеют такой уровень.


15

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

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

Преобразуйте исходный код в файл .cpp и убедитесь, что вы компилируете соответствующим образом.

Если вам нужно придерживаться C, приведенный ниже код (вроде) эквивалентен:


1
Это универсальный проект, и мне нужно использовать C. Есть ли способ сделать то, что я хочу, на C?
xRed

Просто переместите эту функцию за пределы структуры и сделайте так, чтобы она принимала указатель на ваш экземпляр.
user123

Функция client.AddClient () будет невозможна без небольшой сложной магии (см. Другой ответ).
QSQ

14

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


«Немного» решение, подобное JavaScrip
Битман

8

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

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

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

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

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

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

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


У такого подхода есть свои плюсы и минусы. Тот факт, что так делалось всегда , ссылаясь как на не-OO ( do(object, subject)), так и на OO ( subject.do(object)) стратегии упорядочивания функций, не означает, что мы должны прекратить пробовать это. Я полностью считаю правильным отметить, что это не исторический способ написания C, и что C не нужно писать таким образом (то же самое касается многих языков, особенно из процедурной, функциональной или логической парадигм), но мне не нужно активно препятствовать этому шаблону. У этого также есть некоторые преимущества
hiljusti

0

Вы можете передать указатель структуры на функцию как аргумент функции. Это называется передачей по ссылке.

Если вы измените что-то внутри этого указателя, остальные будут обновлены до. Попробуйте вот так:


Нет передачи по ссылке - C. Вы передаете копию указателя, ссылки указателя такие же, а самих указателей нет.
Сержант Кортез

Спасибо за исправление. Я прочитал C pass by reference tutorial от Tutorialspoint. Это отличается от того, что я написал выше?
Хади Хидаят Хаммурапи
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.