C'est une simple question mais la réponse est étonnamment complexe. La réponse courte est que vous pouvez faire ce que vous essayez de faire avec std::bind1st ou boost::bind. Plus la réponse est ci-dessous.
Le compilateur est correct pour vous suggérons d'utiliser &CLoggersInfra::RedundencyManagerCallBack. Tout d'abord, si RedundencyManagerCallBack est une fonction de membre de la fonction elle-même n'appartient pas à une quelconque instance de la classe CLoggersInfra. Il appartient à la classe elle-même. Si vous avez déjà appelé une classe statique fonction avant, vous avez peut-être remarqué que vous utilisez le même SomeClass::SomeMemberFunction de la syntaxe. Étant donné que la fonction elle-même est "statique" dans le sens où il appartient à la classe plutôt que d'un exemple particulier, vous utilisez la même syntaxe. Le " & " est nécessaire parce que techniquement parlant, on ne passe pas directement les fonctions de -- fonctions ne sont pas de vrais objets en C++. Au lieu de cela, vous êtes techniquement en passant l'adresse de la mémoire pour la fonction, c'est un pointeur à l'endroit où la fonction est de donner les consignes en mémoire. La conséquence est la même, vous êtes effectivement " passer une fonction en paramètre.
Mais c'est seulement la moitié du problème dans ce cas. Comme je l'ai dit, RedundencyManagerCallBack la fonction n'est pas "appartenir" à un cas particulier. Mais il semble que vous voulez passer comme un rappel avec une instance particulière à l'esprit. Pour comprendre comment ce faire, vous devez comprendre ce que les fonctions de membre sont vraiment: régulier non défini-dans-toute-la classe des fonctions avec un supplément de paramètre caché.
Par exemple:
class A {
public:
Un (une) : les données(0) {}
void foo(int addToData) { this->data += addToData; }
int données;
};
...
Un an_a_object;
an_a_object.foo(5);
A::foo(&an_a_object, 5); // C'est la même que pour la ligne ci-dessus!
std::cout
Le nombre de paramètres n'A::foo? Normalement, nous aurions dire 1. Mais sous le capot, toto prend vraiment 2. Regarder A::foo définition, il a besoin d'une instance spécifique d'Un pour le " ce " pointeur pour être significatif (le compilateur doit savoir ce qu'est 'ce' est). La façon dont vous habituellement spécifier ce que vous voulez 'ce' est par le biais de la syntaxe MyObject.MyMemberFunction(). Mais ce n'est que sucre syntaxique pour le passage de l'adresse de MyObject comme premier paramètre de MyMemberFunction. De même, lorsque nous déclarons membre des fonctions à l'intérieur des définitions de classe nous ne mettons pas le " il " dans la liste des paramètres, mais c'est juste un cadeau de la langue designers pour enregistrer la saisie. Au lieu de cela, vous devez spécifier qu'une fonction membre statique de refuser automatiquement l'obtention de l'extra " ce paramètre. Si le compilateur C++ traduit l'exemple ci-dessus en code C (à l'origine, le compilateur C++ effectivement travaillé de cette façon), il serait sans doute écrire quelque chose comme ceci:
struct A {
int data;
};
void a_init(A* to_init)
{
to_init->data = 0;
}
void a_foo(A* this, int addToData)
{
this->data += addToData;
}
...
A an_a_object;
a_init(0); // Before constructor call was implicit
a_foo(&an_a_object, 5); // Used to be an_a_object.foo(5);
Revenir à votre exemple, il y a maintenant un problème évident. 'Init' veut un pointeur vers une fonction qui prend un paramètre. Mais &CLoggersInfra::RedundencyManagerCallBack est un pointeur vers une fonction qui prend deux paramètres, il est normal de paramètre et le secret 'de ce paramètre. Donc pourquoi vous obtenez toujours une erreur du compilateur (comme une note de côté: Si vous avez déjà utilisé Python, ce genre de confusion est pourquoi un 'soi' le paramètre est requis pour toutes les fonctions de membre).
Le verbose façon de gérer cela est de créer un objet spécial qui contient un pointeur vers l'instance que vous souhaitez et a une fonction membre appelé quelque chose comme " run " ou "exécuter" (ou surcharge l' '()' opérateur) qui prend les paramètres pour la fonction de membre, et appelle simplement la fonction de membre avec ces paramètres sur la stockées instance. Mais ce serait vous obliger à changer "Init" pour prendre votre objet spécial, plutôt que de les raw d'un pointeur de fonction, et il semble Init est quelqu'un d'autre code. Et de faire une classe spéciale pour chaque fois que ce problème va conduire à l'augmentation du code.
Alors maintenant, enfin, la bonne solution, boost::bind et boost::function, la documentation pour chaque que vous pouvez trouver ici:
boost::bind docs,
boost::function docs
boost::bind vous permettra de prendre une fonction, et un paramètre de la fonction, et de faire une nouvelle fonction lorsque ce paramètre est "verrouillé" en place. Donc, si j'ai une fonction qui additionne deux nombres entiers, je peux utiliser boost::bind pour faire une nouvelle fonction où l'un des paramètres est verrouillé à-dire 5. Cette nouvelle fonction permettra de prendre uniquement un paramètre de type entier, et toujours ajouter 5 spécialement pour elle. En utilisant cette technique, vous pouvez "verrouiller" caché " de ce paramètre à une instance de classe, et de créer une nouvelle fonction qui ne prend qu'un seul paramètre, tout comme vous le voulez (notez que le paramètre masqué est toujours le premier paramètre, et les paramètres normaux viennent dans l'ordre après elle). Regardez les boost::bind docs pour des exemples, ils ont même discuter spécifiquement de l'utiliser pour les fonctions de membres. Techniquement, il est une fonction standard appelé std::bind1st que vous pourriez utiliser, mais les boost::bind est plus général.
Bien sûr, il ya juste un hic. boost::bind fera un joli boost::function pour vous, mais ce n'est toujours pas techniquement raw d'un pointeur de fonction comme Init veut sans doute. Heureusement, boost fournit un moyen de convertir les boost::function du raw pointeurs, comme documenté sur StackOverflow ici. Comment il met en œuvre ce qui est au-delà de la portée de cette réponse, mais c'est intéressant aussi.
Ne vous inquiétez pas si cela vous semble ridiculement dur -- votre question recoupe plusieurs de C++de coins sombres, et boost::bind est incroyablement utile une fois que vous apprendre.