C - funkcja wewnątrz struktury


86

Próbuję stworzyć funkcję wewnątrz struktury, do tej pory mam taki kod:

Błąd : klient.h: 24: 2: błąd: oczekiwano „:”, „,”, „;”, „}” lub „ atrybut ” przed tokenem „{”.

Jaki jest właściwy sposób, aby to zrobić?


12
Nie możesz mieć funkcji w strukturach w C; możesz jednak spróbować z grubsza to zasymulować za pomocą wskaźników funkcji.
— Fingolfin

1
Czy wskaźniki funkcji są akceptowalnym substytutem? stackoverflow.com/a/840703/635678
— Dan O,

Odpowiedzi:


108

Nie można tego zrobić bezpośrednio, ale można emulować to samo, używając wskaźników do funkcji i jawnie przekazując parametr „this”:

Okazuje się, że robienie tego nie kupuje jednak zbyt wiele. W związku z tym nie zobaczysz wielu interfejsów API C zaimplementowanych w tym stylu, ponieważ równie dobrze możesz po prostu wywołać swoją funkcję zewnętrzną i przekazać instancję.


3
X11 API robi coś takiego. Zobacz XImage .
— Hydranix,

1
kod, który znajduje się pod Windows API, jest tego pełen. Z technicznego punktu widzenia „klasa okna” jest strukturą z dwoma wskaźnikami funkcji wywołania zwrotnego i otwartym końcem (dla tych „danych specyficznych dla klasy okna” można podać podczas rejestracji)
— Swift - Friday Pie

1
wykonałem te kroki, ale kiedy zrobię struct.function = newFunction, kompilator wypisze: error: oczekiwano '=', ',', ';', 'asm' lub ' atrybut ' przed '.' żeton
— Bonfra

Byłoby to również przydatne, gdy chciałbyś mieć wspólny cel (np. Dysk twardy), który ma funkcję odczytu i zapisu, ale który różni się od jednego typu dysku twardego do nexf
— Menotdan

Może cię dużo kupić, jeśli rzeczywista implementacja zostanie wybrana w czasie wykonywania. Jeśli masz tylko funkcję statyczną, zawsze musisz ponownie wybrać w ramach tej funkcji przy każdym wywołaniu funkcji, jeśli używasz wskaźnika funkcji, zaznaczenie nastąpi tylko raz. A wybór może się zmieniać nawet przez cały okres istnienia struktury.
— Mecki

24

Jak zauważyli inni, osadzanie wskaźników funkcji bezpośrednio wewnątrz struktury jest zwykle zarezerwowane do specjalnych celów, takich jak funkcja wywołania zwrotnego.

To, czego prawdopodobnie potrzebujesz, to coś w rodzaju wirtualnej tabeli metod.

Teraz dodanie większej liczby operacji nie zmienia rozmiaru client_tstruktury. Ten rodzaj elastyczności jest przydatny tylko wtedy, gdy musisz zdefiniować wiele rodzajów klientów lub chcesz umożliwić użytkownikom client_tinterfejsu rozszerzenie sposobu, w jaki zachowują się operacje.

Taka struktura pojawia się w prawdziwym kodzie. Warstwa OpenSSL BIO wygląda podobnie, a także interfejsy sterowników urządzeń UNIX mają taką warstwę.


15

To zadziała tylko w C ++. Funkcje w strukturach nie są cechą C.

To samo dotyczy twojego klienta.AddClient (); call ... to jest wywołanie funkcji składowej, która jest programowaniem obiektowym, tj. C ++.

Przekonwertuj źródło na plik .cpp i upewnij się, że odpowiednio kompilujesz.

Jeśli chcesz trzymać się C, poniższy kod jest (w pewnym sensie) odpowiednikiem:


1
To jest projekt uni i muszę używać C. Czy jest jakiś sposób, żebym mógł wykonać to, co chcę w C?
— xRed,

Po prostu przenieś tę funkcję poza strukturę i spraw, by akceptowała wskaźnik do Twojej instancji.
— user123

Sprawa client.AddClient () nie byłaby możliwa bez odrobiny skomplikowanej magii (patrz druga odpowiedź).
— QSQ

14

Co powiesz na to?


"Trochę" rozwiązanie podobne do JavaScriptu
— Bitman

8

Próbujesz zgrupować kod według struktury. Grupowanie w C odbywa się według pliku. Umieszczasz wszystkie funkcje i zmienne wewnętrzne w nagłówku lub nagłówku i pliku obiektu „.o” skompilowanym z pliku źródłowego ac.

Nie ma potrzeby odkrywania na nowo orientacji obiektowej od podstaw dla programu C, który nie jest językiem zorientowanym obiektowo.

Widziałem to już wcześniej. To dziwna rzecz. Niektórzy z nich mają niechęć do przekazywania obiektu, który chcą zmienić, w funkcję, która go zmieni, nawet jeśli jest to standardowy sposób.

Obwiniam C ++, ponieważ ukrywało to, że obiekt klasy jest zawsze pierwszym parametrem w funkcji składowej, ale jest ukryty. Wygląda więc na to, że nie przekazuje obiektu do funkcji, mimo że tak jest.

C jest elastyczny i może przyjmować przekazywanie rzeczy przez odniesienie.

Funkcja AC często zwraca tylko bajt stanu lub int i często jest to ignorowane. W twoim przypadku może być odpowiednia forma

addClient byłby w Client.h lub Client.c


Takie podejście ma swoje wady i zalety. To, że zawsze tak było , odnosząc się zarówno do strategii non-OO ( do(object, subject)), jak i OO ( subject.do(object)), nie oznacza, że ​​powinniśmy przestać próbować. Całkowicie uważam, że słuszne jest wskazanie, że to nie jest historyczny sposób, w jaki napisano C, i że C nie musi być pisane w ten sposób (to samo dotyczy wielu języków, zwłaszcza paradygmatów proceduralnych, funkcjonalnych lub logicznych) ale nie musimy aktywnie zniechęcać do wzorca. Ma to również pewne zalety
— hiljusti

0

Możesz przekazać wskaźnik struct, aby działał jako argument funkcji. Nazywało się to przekazywaniem przez odniesienie.

Jeśli zmodyfikujesz coś wewnątrz tego wskaźnika, inne zostaną zaktualizowane do. Spróbuj tak:


Nie ma przejścia przez referencję C. Przekazujesz kopię wskaźnika, referencje wskaźnika są takie same, ale same wskaźniki nie.
— Sierżant Cortez,

Dziękuję za korektę. Przeczytałem C pass przez poradnik referencyjny z Tutorialspoint. Czy to się różni od tego, co napisałem powyżej?
— Hadi Hidayat Hammurabi
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.