fonction en paramètre d'une autre fonction
Bonjour,
Je suis entrein de coder un menu pour un jeu.
j'ajoute des bouton grâce a une méthode :
Code:
AddButton("button name");
J'aimerai faire un lien entre ce bouton est une fonction pour que quand je clique dessus mon programme lance ma fonction.
Exemple: menu.AddButton("Play"); sa me lance la fonction void Play(void);
j'ai pensé a metre un deuxieme parametre a cette fonction et lui donner l'adresse de la fonction mais je sais pas si la méthode est bonne quel est votre avis ?
Problème à la compilation
Game.cpp
Code:
menu.AddButton("Play",Game::Play);
Menu.h
Code:
ligne16 | void AddButton(const char*,void (Game::*)());
Menu.cpp
Code:
void Menu::AddButton(const char* ptext,void (Game::*ptr_function)())
Compilateur
Code:
1 2 3 4 5 6
| ||=== Build: Debug in THELAST (compiler: GNU GCC Compiler) ===|
include\Menu.h|16|error: expected ')' before '::' token|
include\Menu.h|16|error: expected ')' before '::' token|
include\Menu.h|16|error: expected ';' at end of member declaration|
include\Menu.h|16|error: expected id-expression before '*' token|
||=== Build failed: 4 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===| |
Réponse à un MP de Bktero
Bktero m'a envoyé un MP, dont j'ai décidé de vous faire par ici, car il est en rapport avec cette discussion
Citation:
Envoyé par Bktero
Hello,
Du coup j'ai voulu testé ta bibliothèque de signal/slot et j'ai galéré à afficher quelque chose :mouarf:
En fait, je suis très surpris que ce code :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <iostream>
#include "Signal.hpp"
void ma_fonction() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
int main(int, char*[]) {
Tools::Signal signal;
auto connection = signal.connect([]() {
std::cout << "OK" << std::endl;
});
signal.connect([]() {
std::cout << "pas vu..." << std::endl;
});
signal();
} |
n'affiche que "OK"...
Pourrais-tu me dire de quel côté regarder pour comprendre ça ?
@+
Bktero
Tu dois toujours récupérer la connexion renvoyée par la fonction connect. C'est le "troisième larron" qui maintient le lien entre le signal et le slot qui y est connecté: quand elle est détruite, le slot est automatiquement déconnecté.
Cela peut sembler conceptuellement embêtant, mais c'est le seul moyen d'assurer la déconnexion automatique des fonctions membres non statiques sans imposer la restriction (bien plus embêtante encore) que le signal doit être détruit avant les slots qui y sont connectés.
En effet, si je n'avais pas imposé ce "troisième larron" une situation proche de
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
struct Worker{
Worker(Tools::Signal<> & sig){
sig.connect(std::bind(&Worker::print, this));
}
void print(){
std::cout<<"Worker::print() called\n";
}
};
int main(){
Tools::Signal<> sig;
{
Worker worker(sig);
} // oupps... worker is destroyed here... Its "print" function
// is unavaible and will result in a segfault
sig();
return 0;
} |
aurait toujours été possible, et cela n'aurait pas été bon :?:moinsser::scarymov::zekill:
<EDIT>
Grâce à l'ajout de ce "troisième larron", je n'ai plus vraiment de problème, car, si je veux connecter worker à mon signal, les règles de portée jouent en ma faveur:
En effet, un code proche de
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
struct Worker{
void print(){
std::cout<<"Worker::print() called\n";
}
};
int main(){
Tools::Signal<> sig;
{
Worker worker;
}
auto conn = sig.connect(std::bind(&Worker::print, &worker));
sig();
return 0;
} |
ne compilera purement et simplement pas, sous prétexte que worker est inconnu au moment où j'essaye de créer la connexion.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
struct Worker{
void print(){
std::cout<<"Worker::print() called\n";
}
};
int main(){
Tools::Signal<> sig;
{
Worker worker;
auto conn = sig.connect(std::bind(&Worker::print, &worker));
} // conn is destroyed first. related slot is removed from the signal
// worker is destroyed second.
sig(); // calls all connected slots, but worker.print() t is not one of them
return 0;
} |
compilera, mais, comme les règles de portées font que conn sera détruit juste avant worker, et que le slot sera donc déconnecté correctement.
Enfin, une troisième possibilité serait d'ajouter la connexion directement dans la structure Worker, sous une forme qui pourrait être proche de
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| struct Worker{
Worker(Tools::Signal<> & sig):conn{ sig.connect(std::bind(&Worker::print, this))}{
}
void print(){
std::cout<<"Worker::print() called\n";
}
Tools::Connection conn
};
int main(){
Tools::Signal<> sig;
{
Worker worker(sig);
} // worker is destroyed here
// its "conn" member too, of course
// ==>worker.print() is disconnected from sig
sig(); // calls all connected slots, but worker.print() t is not one of them
return 0;
} |
qui compilera, mais qui, encore une fois, ne provoquera pas d'appel à worker.print()
</EDIT>
De la même manière, un code proche de
Ton code devrait donc ressembler à
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <iostream>
#include "Signal.hpp"
void ma_fonction() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
int main(int, char*[]) {
Tools::Signal signal;
auto connection = signal.connect([]() {
std::cout << "OK" << std::endl;
});
auto other = signal.connect(ma_fonction); // et oui, pour une fonction libre ou une fonction membre statique, ca suffit ;)
signal();
} |