web-dev-qa-db-fra.com

Retour du type de pointeur de fonction

Souvent, je trouve le besoin d'écrire des fonctions qui renvoient des pointeurs de fonction. Chaque fois que je le fais, le format de base que j'utilise est le suivant:

typedef int (*function_type)(int,int);

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

Cependant, cela peut devenir fastidieux quand on utilise un grand nombre de fonctions, donc je n’aimerais pas avoir à déclarer une typedef pour chacune (ou pour chaque classe de fonctions)

Je peux supprimer le typedef et déclarer la variable locale renvoyée dans la fonction comme suit: int (*test)(int a, int b);, donnant au corps de la fonction l'apparence suivante:

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

mais alors je ne sais pas quoi définir pour le type de retour de la fonction ..__J'ai essayé:

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

mais cela rapporte une erreur de syntaxe. Comment puis-je déclarer le type de retour pour une telle fonction sans déclarer un typedef pour le pointeur de la fonction. Est-ce même possible? Notez également que je suis conscient du fait que cela semble plus propre de déclarer des modifications de typage, pour chacune des fonctions, cependant, je suis très attentif à structurer mon code pour qu'il soit aussi propre et facile à suivre que possible. La raison pour laquelle je voudrais éliminer les typedefs est qu'ils ne sont souvent utilisés que pour déclarer les fonctions d'extraction et semblent donc redondants dans le code.

46
S E
int (*getFunc())(int, int) { … }

Cela fournit la déclaration que vous avez demandée. De plus, comme ola1olsson notes, il serait bon d’insérer void:

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

Cela signifie que getFunc peut ne prendre aucun paramètre, ce qui peut aider à éviter des erreurs telles que quelqu'un écrivant par inadvertance getFunc(x, y) au lieu de getFunc()(x, y).

53
Eric Postpischil

Vous pouvez probablement faire quelque chose comme:

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

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

mais bon Dieu, j'espère que je n'aurai jamais à déboguer votre code ....

5
yosim

malade laisser cela ici car il était un peu plus délicat que les réponses déjà données, car il faut un pointeur de fonction 

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

et retourne un pointeur de fonction

(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;
}
2
Dmitry

Tout en intégrant du code C dans des classes C++, j'avais le même désir que l'affiche originale: renvoyer un pointeur de fonction à partir d'une fonction sans avoir recours à typedef 'du prototype de pointeur de fonction. J'ai rencontré un problème avec l'exactitude C++ const qui, à mon avis, méritait d'être partagée, même s'il est un peu hors sujet (C++), mais cela concerne directement la question initiale: la syntaxe permettant de renvoyer un pointeur de fonction C sans recourir à un typedef.

Le code ci-dessous définit une classe A qui stocke un pointeur de fonction et l’expose au monde extérieur via l’appel get_f(). C'est la fonction qui doit renvoyer un pointeur de fonction sans typedef.

Le point (qui m'a laissé perplexe pendant un certain temps) était comment déclarer que get_f() était une fonction const, c'est-à-dire qu'elle ne modifierait pas A.

Le code contient 2 variantes: la première utilise un typedef pour le prototype de pointeur de fonction, tandis que la seconde écrit tout dans son intégralité. Le #if bascule entre les deux.

#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

La sortie attendue/souhaitée est:

result = 3

Le point clé est la position du qualificatif const dans la ligne:

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

C'est un exemple stupide, mais c'est simple et cela ne donne pas d'erreur. Il suffit de déclarer des fonctions statiques:

#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;}
1
NicoM

Vous pouvez écrire le code suivant (cela ne fonctionne qu'en C++ 11 et supérieur):

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

Ou, si vous n'aimez pas la déduction de type de retour automatique, vous pouvez spécifier le type à la fin de la fonction (comme ci-dessus, uniquement en C++ 11 et supérieur):

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

Je pense que vous avez trois options:

  1. Stick avec typedef. En fin de compte, c'est le travail de typedef. 
  2. Retourne le vide * et le casting.
  3. Reconsidérer votre architecture logicielle. Peut-être pourriez-vous nous dire ce que vous essayez de faire et voir si nous pouvons vous orienter vers une meilleure direction.
0
Raffaele Rossi