C - функція всередині struct


86

Я намагаюся створити функцію всередині структури, поки що я маю такий код:

Помилка : client.h: 24: 2: помилка: очікується ':', ',', ';', '}' або ' атрибут ' перед маркером '{'.

Який правильний спосіб це зробити?


12
Ви не можете мати функції в структурах на C; Ви можете спробувати приблизно імітувати це за допомогою покажчиків на функції.
Fingolfin

1
Чи є покажчики функцій прийнятною заміною? stackoverflow.com/a/840703/635678
Dan O

Відповіді:


108

Це неможливо зробити безпосередньо, але ви можете емулювати те саме, використовуючи покажчики функцій і явно передаючи параметр "this":

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


3
API X11 робить щось подібне до цього. Див. XImage .
Hydranix

1
код, який лежить під API Windows, повний цього. Технічно "клас вікна" - це структура з двома покажчиками функцій зворотного виклику та з відкритим кінцем (для цих "даних про специфіку класу вікна", які ви можете надати під час реєстрації)
Swift - п'ятниця,

1
виконував ці дії, але коли я роблю struct.function = newFunction, компілятор друкує: помилка: очікується '=', ',', ';', 'asm' або ' атрибут ' перед '.' жетон
Bonfra

Це також було б корисно, коли ви хочете отримати загальну ціль (наприклад, жорсткий диск), яка має функцію читання та функцію запису, але яка варіюється від одного типу жорсткого диска до nexf
Менотдан

Ви можете багато чого придбати, якщо фактичну реалізацію обрано під час виконання. Якщо у вас є лише статична функція, вам завжди потрібно перевибирати цю функцію під час кожного виклику функції, якщо ви використовуєте покажчик функції, вибір відбувається лише один раз. І вибір може змінюватися навіть протягом усього життя структури.
Мекі

24

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

Напевно, вам потрібно щось більше схоже на віртуальну таблицю методів.

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

Така структура справді відображається у реальному коді. Подібним виглядає рівень OpenSSL BIO, а також інтерфейси драйверів пристроїв UNIX мають такий рівень.


15

Це буде працювати лише на C ++. Функції в структурах не є особливістю C.

Те саме стосується і вашого клієнта.AddClient (); виклик ... це виклик функції-члена, яка є об'єктно-орієнтованим програмуванням, тобто С ++.

Перетворіть своє джерело у файл .cpp і переконайтесь, що ви компілюєте відповідним чином.

Якщо вам потрібно дотримуватися C, код нижче є (начебто) еквівалентом:


1
Це уні-проект, і я повинен використовувати C. Чи є спосіб досягти того, що я хочу в C?
xRed

Просто перемістіть цю функцію за межі структури і змусьте її прийняти покажчик на ваш екземпляр.
user123

Річ client.AddClient () не буде можливою без складної магії (див. Іншу відповідь).
QSQ

14

Як щодо цього?


"Трохи" рішення на зразок JavaScrip
The Bitman

8

Ви намагаєтесь згрупувати код відповідно до struct. C групування відбувається за файлами. Ви поміщаєте всі функції та внутрішні змінні в заголовок або заголовок та файл ".o" об'єкта, складений із вихідного файлу змінного струму.

Необов’язково винаходити об’єктну орієнтацію з нуля для програми на С, яка не є об’єктно-орієнтованою мовою.

Я це вже бачив. Це дивна річ. Кодери, деякі з них, мають огиду передавати об'єкт, який вони хочуть змінити, у функцію для його зміни, хоча це стандартний спосіб це зробити.

Я звинувачую C ++, тому що він приховував той факт, що об'єкт класу завжди є першим параметром у функції-члена, але він прихований. Отже, схоже, це не передача об’єкта у функцію, хоча вона і є.

C є гнучким і може приймати передані речі за посиланням.

Функція змінного струму часто повертає лише байт стану або int, і це часто ігнорується. У вашому випадку це може бути відповідна форма

addClient буде в Client.h або Client.c


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

0

Ви можете передати вказівник на структуру як функцію аргументу функції. Це називається передача за посиланням.

Якщо ви щось зміните всередині цього вказівника, інші будуть оновлені до. Спробуйте так:


Немає передачі за посиланням C. Ви передаєте копію вказівника, посилання на вказівник однакові, а самі вказівники ні.
Сержант Кортес

Дякую за виправлення. Я прочитав підручник з передачі C від Tutorialspoint. Чи відрізняється це від того, що я писав вище?
Хаді Хідаят Хаммурапі,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.