2011-06-30 3 views
1

J'ai une fonction Foo et une classe CDelegate.const référence au pointeur de fonction

typedef void (*typeFctPtr)(void*); 


void Foo(void* dummy) 
{ 
    cout << "Foo\n"; 
} 


class CDelegate 
{ 
    public: 

    CDelegate (const typeFctPtr& f_ref_Wrapper, void* f_pvSubscriber) 
    : m_ref_Wrapper(f_ref_Wrapper), m_pvSubscriber(f_pvSubscriber) 
    { 
    } 

    inline void operator()() const 
    { 
    (*m_ref_Wrapper)(0); 
    } 

    inline void operator=(const CInterruptDelegate& D) 
    { 
    } 

private: 
    void* m_pvSubscriber; 
    const typeFctPtr& m_ref_Wrapper; 
}; 

Une deuxième classe a un membre statique static CDelegate m_Delegate; que j'initialiser en utilisant le constructeur comme ceci:

CInterruptDelegate CSpi1::m_Delegate(FreeFunction, 0); 

Je veux appeler Foo en appelant l'opérateur() de mon objet statique: CSpi1::m_Delegate();

Je reçois une exception à (*m_ref_Wrapper)(0); Y at-il un problème avec la syntaxe? Je ne suis pas sûr que ce que j'essaie de faire soit possible. J'ai une solution de travail où le constructeur de CDelegate ne prend pas une référence const d'un pointeur de fonction mais le pointeur de fonction lui-même. Je peux alors appeler la fonction dans l'opérateur() sans problèmes. Je veux utiliser une référence const parce que l'appel de pointeur de fonction ne peut pas être optimisé et j'espère que l'appel via la référence const peut car tout devrait être connu au moment de la compilation.

+0

Avez-vous essayé d'appeler simplement 'm_ref_Wrapper (0);'? – iammilind

+0

Je serais surpris si l'optimiseur est capable de supprimer l'appel indirect avec une référence ou un pointeur. Mais un appel indirect n'est vraiment pas si cher. –

+0

@Cat Plus Plus, j'utilise ce mécanisme pour la gestion des interruptions dans un système embarqué. boost :: function fait tout ce dont j'ai besoin mais est plutôt lent. De plus, le logiciel fonctionne en prenant l'argument comme un pointeur de fonction. Je veux optimiser maintenant en utilisant une référence const ... au moins essayer de :) – Mirco

Répondre

1

Vous détenez une référence à un pointeur sur une fonction (et le pointeur est un temporaire qui a été détruit au moment où vous l'utilisez, donc les choses tournent mal).

Essayez de changer typedef pour être un type de fonction:

typedef void typeFct(void*); 
... 
const typeFct & m_ref_Wrapper; 

Ensuite, avec votre code existant, vous vous retrouverez avec une référence à une fonction, et vous serez bien. Ou vous pouvez stocker un pointeur sur la fonction - const typeFct *.

Et dans les deux cas, l'appel peut simplement être m_ref_Wrapper(0).

En général, je préfère typedef types de fonctions plutôt que pointer-to ou référence-à, si seulement parce que la syntaxe est moins laide.

+0

Merci, je peux compiler ceci et je ne reçois aucune erreur de minuterie d'exécution. Mais je reçois l'avertissement 'avertissement C4180: qualificatif appliqué au type de fonction n'a pas de sens; ignoré' pour ces lignes: 'CDelegate (const typeFct & f_ref_Wrapper, void * f_pvSubscriber)' et 'const typeFct & m_ref_Wrapper;' – Mirco

+0

@Mirco Ah oui, mon erreur. Il ne devrait pas y avoir de const appliquée à typeFct n'importe où. const est idéal pour les données, sans signification pour les fonctions. –

1

Je crois que le problème est la déclaration du membre:

const typeFctPtr& m_ref_Wrapper; 

Au lieu de cela, essayez de laisser tomber le &:

const typeFctPtr m_ref_Wrapper; 

Une référence doit toujours faire référence un autre objet existant. Dans ce cas, il se référera à l'objet temporaire créé pour contenir la référence au pointeur au moment où le constructeur est appelé.

Pendant que nous y sommes, je suggère que vous deviez également supprimer la référence du constructeur. La raison en est qu'il n'y a pas de gain lorsque vous travaillez avec scalaire: s.

Une autre chose qui rendrait votre code plus lisible est si vous voulez typedef le type de la fonction, plutôt que le pointeur vers la fonction. De cette façon, il serait clair que vous passez un pointeur.

Ce qui suit est une version allégée qui résume les changements que je propose ci-dessus:

typedef void (typeFct)(void*); 

class CDelegate 
{ 
    public: 

    CDelegate (typeFct * f_Wrapper, void* f_pvSubscriber) 
    : m_ref_Wrapper(f_Wrapper), m_pvSubscriber(f_pvSubscriber) 
    { 
    } 

    inline void operator()() const 
    { 
    (*m_ref_Wrapper)(0); 
    } 

private: 
    void* m_pvSubscriber; 
    typeFct * m_ref_Wrapper; 
}; 
+0

+1 semble juste juste –

+0

Merci! Btw, j'ai appris quelque chose de nouveau de votre poste, je ne savais pas que vous pouvez faire référence à une fonction. – Lindydancer

+0

@ Lindydancer, je pense que c'est ma solution de travail en utilisant un pointeur de fonction au lieu d'utiliser une référence à un - avec la différence de typedef. Je m'en souviendrai et commencerai à typedef le type de la fonction dans le futur :) Malheureusement, je ne peux pas +1 (encore <15) .. Merci d'aider – Mirco

Questions connexes