MySQL Java JavaScript PHP Python HTML-CSS C-sharp C++ Go

Pointer la funcție ca valoare returnată

O funcție poate returna un pointer către altă funcție. Acest lucru este util în cazul în care avem un număr limitat de opțiuni — funcții care pot fi executate — și trebuie să alegem una dintre ele. Alegerea și setul de opțiuni sunt determinate de o funcție intermediară.

Să analizăm un exemplu simplu:

#include <iostream>
  
void goodmorning();
void goodevening();
void(*message(unsigned))();
  
int main()
{
    void(*action)(){message(10)};    // pointer către funcția selectată
    action();                       // Good Morning!
    action = message(16);           // obținem altă funcție
    action();                       // Good Evening!
}
  
void(*message(unsigned hour))()
{
    if (hour > 15)
        return goodevening;
    else
        return goodmorning;
}
void goodmorning()
{
    std::cout << "Good Morning!" << std::endl;
}
void goodevening()
{
    std::cout << "Good Evening!" << std::endl;
}

Aici este definită funcția message, care în funcție de ora transmisă ca parametru, returnează una dintre funcțiile goodmorning sau goodevening. Să analizăm semnătura funcției:

void(*message(unsigned hour))()

Mai întâi este indicat tipul funcției returnate — void, deoarece funcțiile goodmorning și goodevening nu returnează nimic. În paranteze este declarat numele funcției message și parametrul ei — unsigned. După aceea, se specifică parametrii funcției returnate — în acest caz, () fiindcă nu are parametri.

Numele funcției este de fapt un pointer la ea, deci în message putem face:

return goodmorning;

Pentru a stoca pointerul, se definește o variabilă:

void(*action)();

Aceasta este un pointer către o funcție fără parametri și cu tip de retur void.

Exemplu de apel:

action = message(16); // returnează goodevening
action();             // apelează funcția

Exemplu mai complex: în funcție de alegerea utilizatorului, este returnată o operație aritmetică:

#include <iostream>
  
int add(int, int);
int subtract(int, int);
int multiply(int, int);
int(*select(int))(int, int);
  
int main()
{
    int(*action)(int, int) {select(1)};
    std::cout << action(8, 5) << std::endl; // 13
 
    action = select(2);
    std::cout << action(8, 5) << std::endl; // 3
 
    action = select(3);
    std::cout << action(8, 5) << std::endl; // 40
}
  
int(*select(int choice))(int, int)
{
    switch (choice)
    {
        case 2:
            return subtract;
        case 3:
            return multiply;
        default:
            return add;
    }
}
int add(int x, int y) { return x + y; }
int subtract(int x, int y) { return x - y; }
int multiply(int x, int y) { return x * y; }

Aici, funcția select() primește o alegere (1, 2 sau 3) și returnează funcția corespunzătoare. Tipul funcției este:

if (choice >0 && choice<4)
    return actions[choice - 1];
else
    return nullptr;

adică o funcție care returnează un pointer la funcție ce primește doi int și returnează un int.

Putem adăuga o verificare suplimentară, dacă alegerea nu corespunde unei funcții:

#include <iostream>
  
int add(int, int);
int subtract(int, int);
int multiply(int, int);
int(*select(int))(int, int);
  
int main()
{
    int(*action)(int, int) {select(14)};
    if(action)
    {
        std::cout << action(8, 5) << std::endl;
    }
    else
    {
        std::cout << "Undefined" << std::endl;
    }
}
  
int(*select(int choice))(int, int)
{
    int (*actions[])(int, int){ add, subtract, multiply };
    if (choice > 0 && choice < 4)
        return actions[choice - 1];
    else
        return nullptr;
}
int add(int x, int y) { return x + y; }
int subtract(int x, int y) { return x - y; }
int multiply(int x, int y) { return x * y; }