2010-11-26 11 views
2

Je suis amusant avec des macros (non)erreurs macro avec fonction membre

#include <iostream> 

using namespace std; 

#define DEF_ATTRIBUTE(type, name) type name;\ 
    typedef void (*type_name_t)(CLASS_NAME*);\ 
    type_name_t ptr_type_name;\ 
    void type_name(){(ptr_type_name = &CLASS_NAME::type_name);}\ 

class Test 
{ 
    public: 
     #define CLASS_NAME Test 
     DEF_ATTRIBUTE(int, i_Test); 

     void Print() 
     { 
      cout << "Test::Print()" << endl; 
     } 
}; 

int main() 
{ 
    Test t; 
    t.Print(); 
} 

qui se développe pour:

class Test 
{ 
    public: 

     int i_Test; typedef void (*type_name_t)(Test*); type_name_t ptr_type_name; void type_name(){(ptr_type_name = &Test::type_name);}; 

     void Print() 
     { 
      cout << "Test::Print()" << endl; 
     } 
}; 

et donne l'erreur du compilateur:

main.cpp: In member function void Test::type_name():
main.cpp:16: error: cannot convert void (Test::)() to void ()(Test*) in assignment

Comme autant que je peux comprendre, les pointeurs de fonction sont équivalents. Qu'est-ce que je fais mal?

+0

macros Utilisation en C++? Mettre des macros au milieu du code? – Raveline

+0

Nous y revoilà. Si vous ne l'aimez pas, ne postez pas. Je ne demande pas d'avis, juste une réponse. – nakiya

+0

Je pense que c'est l'une de ces macros carrées essayant de s'adapter à un problème rond. – Skizz

Répondre

2

Les pointeurs de fonction ne sont pas équivalents.

void (*type_name_t)(Test*) 

n'est pas la même chose que

&Test::type_name 

Votre pointeur de fonction est de type: un pointeur vers une fonction qui prend un argument, un pointeur de test et retourne aucune valeur.

Qu'est-ce que vous voulez est un pointeur à fonction membre, en particulier, un pointeur vers une fonction membre qui ne prend aucun argument et ne renvoie aucune valeur:

void (Test::*type_name_t)(); // note the empty parameter list! 
+0

Bien sûr, cela ne résout pas le problème 'using macros'. Essayez d'avoir deux DEF_ATTRIBUTE dans une classe! – Skizz

4

Les types de pointeurs ne sont pas équivalents: Un type_name_t est un pointeur de fonction (un pointeur vers une fonction libre), alors que &Test::type_name est un pointeur vers une fonction membre. C'est ce que le compilateur vous dit.

La raison pour laquelle vous ne pouvez pas convertir un pointeur en fonction membre en un pointeur de fonction simple est qu'une fonction membre (non statique) possède un paramètre caché this. Vous ne pouvez pas appeler une fonction membre via un pointeur de fonction, car il n'y aurait aucun moyen de passer le paramètre this. Vous essayez d'expliquer cela en donnant à votre type_name_t un paramètre CLASS_NAME* - conceptuellement la bonne chose à faire, mais C++ ne fonctionne pas de cette façon.

Au lieu de cela, ce que vous devez faire est de Delare type_name_t comme un pointeur vers une fonction membre:

typedef void (CLASS_NAME::*type_name_t)(); 

(Untested J'espère que la syntaxe est juste, je ne pas utiliser des pointeurs vers des fonctions membres sur un. tous les jours.)

+1

Comment devrait Je change 'type_name_t' pour faire correspondre' & Test :: type_name'? – nakiya

+0

'void (Test :: * type_name_t) (Test *)' même si je suis assez sûr que ce n'est pas ce que vous voulez faire. vous voulez changer la méthode 'type_name()' en une méthode statique –

+0

@nakiya: Réponse éditée pour montrer comment la déclaration de 'type_name_t' devrait être changée. –

1

Les types sont différents.

&Test::type_name est un pointeur vers une fonction membre de la classe Test alors type_name_t ne peut pas tenir l'adresse de toute fonction de membre de la classe Test. C'est juste un pointeur sur une fonction libre (pas sur une fonction membre).

Essayez ceci:

#define CLASS_NAME Test 
#define DEF_ATTRIBUTE(type, name) type name;\ 
    typedef void (CLASS_NAME::*type_name_t)();\ 
    type_name_t ptr_type_name;\ 
    void type_name(){(ptr_type_name = &CLASS_NAME::type_name);}\ 
Questions connexes