C++ typedef membre fonction signature syntaxe

Je veux déclarer une définition de type pour une signature de fonction membre. La fonction globale typedefs ressemble à ceci:

typedef int (function_signature)(int, int);
typedef int (*function_pointer) (int, int);

Mais je ne suis pas capable de la même chose pour une fonction membre:

typedef int (foo::memberf_signature)(int, int);   // memberf_pointer is not a member of foo
typedef int (foo::*memberf_pointer)(int, int);

Cela me semble logique, car "foo::" est la syntaxe pour accéder à un membre de la classe foo. Comment puis-je taper juste la signature?

22
demandé sur 0xbadf00d 2011-01-28 22:31:18

5 réponses

Pour des questions concernant la syntaxe du pointeur de fonction maladroite, j'utilise personnellement une feuille de triche: le tutoriel des pointeurs de fonction (téléchargeable ici , Merci à Vector pour l'avoir signalé).

La signature d'une fonction membre, cependant, est un peu différente de la signature d'une fonction régulière, comme vous l'avez connu.

Comme vous le savez probablement, une fonction membre a un paramètre caché, this, dont le type doit être spécifié.

typedef int (Foo::*Member)(int, int);

Laisse vous spécifiez que le premier élément passé à la fonction sera un Foo* (et donc votre méthode prend vraiment 3 arguments, quand vous y pensez, pas seulement 2.

Cependant, il y a aussi une autre raison, pour vous forcer à spécifier le type.

Un pointeur de fonction peut faire référence à une fonction virtuelle, auquel cas les choses peuvent devenir assez compliquées. Par conséquent, la taille même de la représentation en mémoire change en fonction du type de fonction. En effet, sur Visual Studio, un la taille du pointeur de fonction peut varier entre 1 et 4 fois la taille d'un pointeur normal. Cela dépend si la fonction est virtuelle, notamment.

Par conséquent, la classe à laquelle la fonction se réfère fait partie de la signature, et il n'y a pas de contournement.

11
répondu Matthieu M. 2017-05-23 12:10:18

Vous pouvez factoriser la classe cible dans le C++ moderne (post 11) en utilisant les qualités 'typedefing' detemplate aliases . Ce dont vous avez besoin ressemblerait à:

template<typename T>
using memberf_pointer = int (T::*)(int, int); 

Pourtant, au point de déclaration, un pointeur vers la fonction membre utilisant cette syntaxe devrait spécifier la classe cible:

// D is a member function taking (int, int) and returning int
memberf_pointer<foo> mp = &foo::D; 
5
répondu Nikos Athanasiou 2015-07-27 09:36:35

Cela fonctionne pour moi:

#include <iostream>

class foo
  {
public:
  int g (int x, int y) { return x + y ; }
  } ;

typedef int (foo::*memberf_pointer)(int, int);

int main()
  {
  foo f ;
  memberf_pointer mp = &foo::g ;
  std::cout << (f.*mp) (5, 8) << std::endl ;
  }
2
répondu TonyK 2011-01-28 21:24:40

La raison pour laquelle cela ne fonctionne pas avec votre syntaxe actuelle est que la priorité de l'opérateur dicte que vous faites référence à une fonction nommée foo::memberf_signature, pas n'importe quel type.

Je ne sais pas avec certitude si vous pouvez le faire ou non, mais je n'ai pas pu trouver une combinaison de parenthèses qui a incité le code à compiler avec g++ 4.2.

1
répondu Mark B 2011-01-28 19:57:13

Eh bien, fondamentalement, cela ne peut pas fonctionner (au moins je ne connais aucun moyen d'utiliser g++); En utilisant le compilateur borland C++, il y aurait le mot-clé _ _ closure.

La raison pour laquelle il ne compile pas est, que sizeof le functionpointer (sur une machine x86) occupe toujours >; mais si vous voulez pointer vers une signature de classe (interface), la sizeof doit être 64bit: 32 bits pour le pointeur (comme l'interface de classe est dans la mémoire une seule fois) et 32 bits pour la fonction réelle

Mais la fermeture __ mot-clé est un langage bcb 'hack' non standardisé...

-3
répondu googling 2011-01-28 20:08:17