Terugkerend functieaanwijzertype

Vaak vind ik de noodzaak om functies te schrijven die functiewijzers retourneren. Wanneer ik dat doe, is het basisformaat dat ik gebruik:

typedef int (*function_type)(int,int);
function_type getFunc()
{
   function_type test;
   test /* = ...*/;
   return test;
}

Dit kan echter omslachtig worden bij het omgaan met een groot aantal functies, dus ik zou graag geen typedef hoeven te declareren voor elke functie (of voor elke klasse van functies)

Ik kan de typedef verwijderen en de lokale variabele declareren die in de functie wordt geretourneerd als:
int (*test)(int a, int b);waardoor de hoofdtekst van de functie er als volgt uitziet:

{
     int (*test)(int a, int b);
     test /* = ...*/;
     return test;
}

maar dan weet ik niet wat ik moet instellen voor het retourtype van de functie.
Ik heb geprobeerd:

int(*)(int,int) getFunc()
{
    int (*test)(int a, int b);
    test /* = ...*/;
    return test;
}

maar dat meldt een syntaxisfout. Hoe declareer ik het retourtype voor een dergelijke functie zonder een typedef voor de functieaanwijzer te declareren. Is het zelfs mogelijk? Merk ook op dat ik me ervan bewust ben dat het lijkt alsof het schoner zou zijn om typedefs te declareren, voor elk van de functies, maar ik ben heel voorzichtig om mijn code zo schoon en gemakkelijk te volgen mogelijk te structureren. De reden dat ik de typedefs wil elimineren, is dat ze vaak alleen worden gebruikt om de ophaalfuncties te declareren en daarom overbodig lijken in de code.


Antwoord 1, autoriteit 100%

int (*getFunc())(int, int) { … }

Dat levert de gevraagde verklaring op. Bovendien, zoals ola1olssonopmerkt, zou het goed zijn om voidin te voegen:

int (*getFunc(void))(int, int) { … }

Dit zegt dat getFuncgeen parameters mag aannemen, wat fouten kan helpen voorkomen, zoals iemand die per ongeluk getFunc(x, y)schrijft in plaats van getFunc()(x, y).


Antwoord 2, autoriteit 10%

Je kunt waarschijnlijk iets doen als:

int foo (char i) {return i*2;}
int (*return_foo()) (char c)
{
   return foo;
}

maar god, ik hoop dat ik nooit je code hoef te debuggen….


Antwoord 3, autoriteit 4%

Ik zal dit hier laten omdat het een beetje lastiger was dan de antwoorden die al zijn gegeven, omdat er een functiewijzer voor nodig is

(int (__cdecl *)(const char *))

en retourneert een functieaanwijzer

(int (__cdecl *)(const char *))

#include <stdio.h>
int (*idputs(int (*puts)(const char *)))(const char *) {
    return puts;
}
int main(int argc, char **argv)
{
    idputs(puts)("Hey!");
    return 0;
}

Antwoord 4, autoriteit 3%

Terwijl ik wat C-code in C++-klassen wikkelde, had ik dezelfde wens als de originele poster: een functieaanwijzer van een functie retourneren zonder toevlucht te nemen tot typedef‘ing van het prototype van de functieaanwijzer. Ik stuitte op een probleem met de correctheid van C++ constwaarvan ik dacht dat het de moeite waard was om te delen, ook al is het een beetje off-topic (C++), maar het heeft wel rechtstreeks betrekking op de oorspronkelijke vraag: de syntaxis voor het retourneren van een C-functie pointer zonder toevlucht te nemen tot een typedef.

De onderstaande code definieert een klasse Adie een functieaanwijzer opslaat en deze aan de buitenwereld blootstelt via de get_f()-aanroep. Dit is de functie die een functieaanwijzer zou moeten retourneren zonder een typedef.

Het punt (waar ik een tijdje van dwaalde) was hoe te verklaren dat get_f()een const-functie was, dat wil zeggen dat het A.

De code bevat 2 varianten: de eerste gebruikt een typedef voor het prototype van de functieaanwijzer, terwijl de tweede alles volledig uitschrijft. De #ifschakelt tussen de twee.

#include <iostream>
int my_f(int i)
{
  return i + 1;
}
#if 0 // The version using a typedef'ed function pointer
typedef int (*func_t)(int);
class A
{
public:
  A(func_t f) : m_f(f) {}
  func_t get_f() const { return m_f; }
private:
  func_t m_f;
};
int main(int argc, char *argv[])
{
  const A a(my_f);
  std::cout << "result = " << a.get_f()(2) << std::endl;
}
#else // The version using explicitly prototyped function pointer    
class A
{
public:
  A(int (*f)(int)) : m_f(f) {}
  int (*get_f() const)(int) { return m_f; }
private:
  int (*m_f)(int);
};
int main(int argc, char *argv[])
{
  const A a(my_f);
  std::cout << "result = " << a.get_f()(2) << std::endl;
}
#endif

De verwachte/gewenste output is:

result = 3

Het belangrijkste punt is de positie van de constkwalificatie in de regel:

int (*get_f() const)(int) { return m_f; }

Antwoord 5

Dit is een stom voorbeeld, maar het is eenvoudig en geeft geen fouten. Het gaat alleen om het declareren van statische functies:

#include <stdio.h>
#include <stdlib.h>
void * asdf(int);
static int * hjkl(char,float);
main() {
  int a = 0;
  asdf(a);
 }
void * asdf(int a) {return (void *)hjkl; }
static int * hjkl(char a, float b) {int * c; return c;}

Antwoord 6

Ik denk dat je drie opties hebt:

  1. Blijf bij typedef. Uiteindelijk is het de taak van typedef.
  2. Retour ongeldig* en het casten ervan.
  3. Heroverweeg uw software-architectuur. Misschien kun je met ons delen wat je probeert te bereiken en kijken of we je een betere richting kunnen geven.

Antwoord 7

Je kunt de volgende code schrijven (het werkt alleen in C++11 en hoger):

//C++11
auto func(...) {
    int (*fptr)(...) ret = ...
    //Do sth.
    return ret;//C++11 compiler will automatically deduce the return type for you
}

Of, als u niet van automatische aftrek van het retourtype houdt, kunt u het type aan het einde van de functie specificeren (hetzelfde als hierboven, alleen in C++11 en hoger):

//C++11
auto func(...) -> int (*)(...) { /* Do sth. */ }

Other episodes