Przekazywanie funkcji jako argumentów
Część sekcji Programowanie obiektowe ścieżki C w Coddy. Lekcja 36 z 61.
Jednym z najbardziej zaawansowanych zastosowań wskaźników do funkcji jest przekazywanie ich jako argumentów do innych funkcji. Pozwala to wprowadzić niestandardowe zachowanie do funkcji bez modyfikowania jej kodu: technikę tę czasami nazywa się wywołaniem zwrotnym.
Rozważ funkcję, która wykonuje obliczenia na dwóch liczbach. Zamiast wpisywać operację na stałe, możesz przyjąć wskaźnik do funkcji określający, jaką operację wykonać:
typedef int (*Operation)(int, int);
int compute(int a, int b, Operation op) {
return op(a, b);
}Funkcja compute nie wie, czy dodaje, odejmuje, czy robi coś zupełnie innego. Po prostu wywołuje funkcję, która została jej przekazana:
int add(int a, int b) { return a + b; }
int multiply(int a, int b) { return a * b; }
int main() {
printf("%d\n", compute(5, 3, add)); // Wynik: 8
printf("%d\n", compute(5, 3, multiply)); // Wynik: 15
return 0;
}Zauważ, że ta sama funkcja compute zwraca różne wyniki w zależności od tego, którą funkcję jej przekażemy. Ten wzorzec jest podstawą pisania elastycznego, wielokrotnego użytku kodu. Strukturę tworzysz raz, a użytkownicy twojej funkcji dostarczają konkretną logikę, której potrzebują.
Wyzwanie
ŁatwyNapisz funkcję apply_twice, która przyjmuje dwie liczby całkowite oraz kod operacji, wykonuje tę operację na liczbach dwukrotnie po kolei i zwraca końcowy wynik.
Twoja funkcja otrzyma kod operacji określający, której operacji użyć. Musisz zdefiniować funkcje operacji w swoim rozwiązaniu i przekazać je do funkcji pomocniczej compute, która przyjmuje wskaźnik do funkcji.
Uwaga: potrzebne są tylko funkcje. Testy wywołują bezpośrednio apply_twice i sprawdzają zwracaną przez nią wartość, więc nie odczytuj danych wejściowych ani niczego nie wypisuj.
Wymagana struktura:
- Zdefiniuj
typedefo nazwieOperationdla wskaźnika do funkcji, która przyjmuje dwa parametry typuinti zwraca wartość typuint - Zdefiniuj dwie funkcje operacji:
add(zwraca a + b) imultiply(zwraca a * b) - Zdefiniuj funkcję
compute, która przyjmuje dwie liczby całkowite i wskaźnik do funkcji typuOperation, a następnie zwraca wynik wywołania tej operacji - W funkcji
apply_twicewybierz odpowiednią operację na podstawie kodu, a następnie dwukrotnie użyjcompute: najpierw z pierwotnymi liczbami, a potem z wynikiem i ponownie drugą liczbą
Logika:
- Wybierz funkcję operacji na podstawie
op_code(1 = dodawanie, 2 = mnożenie) - Wywołaj
compute(a, b, operation), aby uzyskać wynik pośredni - Wywołaj
compute(intermediate, b, operation), aby uzyskać końcowy wynik - Zwróć końcowy wynik
Parametry:
a(int): pierwsza liczbab(int): druga liczbaop_code(int): kod operacji (1 oznacza dodawanie, 2 oznacza mnożenie)
Zwraca: wynik po dwukrotnym wykonaniu operacji po kolei (int)
Przykład: Dla a = 5, b = 3, op_code = 1 (dodawanie):
- Pierwsze obliczenie: 5 + 3 = 8
- Drugie obliczenie: 8 + 3 = 11
- Zwróć: 11
Dla a = 2, b = 4, op_code = 2 (mnożenie):
- Pierwsze obliczenie: 2 × 4 = 8
- Drugie obliczenie: 8 × 4 = 32
- Zwróć: 32
Spróbuj swoich sił
int apply_twice(int a, int b, int op_code) {
// Napisz kod tutaj
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania modularnego
Pliki nagłówkoweZabezpieczenia przed wielokrotnym dołączeniemPliki źródłoweFunkcje statycznePodsumowanie: kalkulator modularny4Enkapsulacja
Koncepcja niejawnych wskaźnikówDefiniowanie niejawnych strukturGettery i setteryWalidacja w setterachPowtórka: tajemnicze pudełko7Wskaźniki do funkcji
Deklarowanie wskaźników do funkcjiWywoływanie funkcji przez wskaźnikiTypedef dla wskaźników do funkcjiPrzekazywanie funkcji jako argumentówPodsumowanie: wybór działania kalkulatora2Obiekty i metody
Struktury jako obiektyWskaźnik „self”Poprawność constWskaźnik czy wartośćMetody pomocniczePodsumowanie: menedżer punktów5Projekt: Proste konto bankowe
Konfiguracja projektuImplementacja konta8Polimorfizm
Wskaźniki do funkcji w strukturachSymulowanie metodKoncepcja interfejsuImplementowanie interfejsówIteracja polimorficznaPodsumowanie: Greeter11Wzorce projektowe w C
Wzorzec SingletonWzorzec fabrykiWzorzec iteratoraPodsumowanie: fabryka loggera3Cykl życia obiektu
Wzorzec konstruktoraWzorzec destruktoraInicjalizacja na stosieKopia głębokaPodsumowanie: klasa opakowująca ciąg znaków6Dziedziczenie przez kompozycję
Osadzanie strukturZasada pierwszego elementuDostęp do elementów klasy nadrzędnejKonwersja w górę hierarchiiPodsumowanie: hierarchia kształtów9Projekt: Rysownik kształtów
Przegląd projektuImplementacja kołaImplementacja prostokątaZastosowanie polimorfizmuKontener kształtówPoćwicz samodzielnie: Kompilator C online