Título: Puntero a funcion como argumento
Publicado por: _Enko en 9 Enero 2015, 22:10 pm
Holas estimados , estaba jugando un poco con c++ para crear una clase que manejara menus de consola. Hasta ahora tengo algo funcionando como esto: void proc1(void){ std::cout << "proc1" << std::endl; } void proc1a(void){ std::cout << "proc1a" << std::endl; } void proc1b(void){ std::cout << "proc1b" << std::endl; } void proc2(void){ std::cout << "proc 2" << std::endl; } void proc3a(void){ std::cout << "proc 3a" << std::endl; } void proc3b(void){ std::cout << "proc 3b" << std::endl; } void proc3c(void){ std::cout << "proc 3c" << std::endl; } int main(int argc, char* argv[]){ CMenu menu; menu.AddMenu("OPCION 1", proc1); menu.AddSubMenu("OPCION1A", proc1a, 1); //submenu de la opcion 1 menu.AddSubMenu("OPCION1B", proc1b, 1); menu.AddMenu("OPCION 2", proc2); menu.AddMenu("OPCION 3", NULL); //opcion 3 separador, no tendria funcion menu.AddSubMenu("OPCION3A", proc3a, 3); //submenu de la opcion 3 menu.AddSubMenu("OPCION3B", proc3b, 3); menu.AddSubMenu("OPCION3C", proc3c, 3); menu.PrintMenu(); menu.DoMenu(); return 0; }
El resultado es algo asi: 1: OPCION 1 11: OPCION1A 12: OPCION1B 2: OPCION 2 3: OPCION 3 31: OPCION3A 32: OPCION3B 33: OPCION3C 0: SALIR Eliga una Opcion:
Por ejemplo si se elige la opcion 11, se llamará a proc1a(), y esto se repite hasta que se elija salir. El problema es, el puntero a funcion como parametro lo tengo defenido asi: typedef void(*callback_proc_)(void); inline void CMenu::AddMenu(const char* cap, callback_proc_ proc){
Con esta estructura, estoy forzando que el procedimiento que esta asociado al item del menu es "void name(void)" Como se podría hacer para poder pasar como parametro a AddMenu() una funcion con numero y tipo de parametros desconocido? Saludos Y gracias
Título: Re:
Publicado por: ivancea96 en 9 Enero 2015, 22:47 pm
Conviértelo a void*.
Título: Re: Puntero a funcion como argumento
Publicado por: _Enko en 9 Enero 2015, 22:58 pm
Pero si lo convierto a void* el puntero a funcion tendria un argumento un puntero a void. Y lo que en realidad creo que necesito es tratar de pasarle como parametro una cantidad de parametros desconocida de tipo desconocido. #include <vector> #include <string> #include <iostream> typedef void(*callback_proc_)(void); class CMenu; class MenuItem{ public: MenuItem(const char* cap, callback_proc_ proc):caption_(cap),proc_(proc){} ~MenuItem(){ submenu_.clear(); } friend class CMenu; private: callback_proc_ proc_; std::string caption_; std::vector<MenuItem> submenu_; }; class CMenu{ public: inline void AddMenu(const char* cap, callback_proc_ proc); inline void AddSubMenu(const char* cap, callback_proc_ proc, int parent); inline void PrintMenu(); inline void DoMenu(); CMenu(); ~CMenu(); private: std::vector<MenuItem> menu_; }; CMenu::CMenu(){ menu_.push_back(MenuItem("SALIR", NULL)); } CMenu::~CMenu(){ for(int i = 1; i < menu_.size(); ++i){ menu_[i].submenu_.clear(); } menu_.clear(); } inline void CMenu::AddMenu(const char* cap, callback_proc_ proc){ menu_.push_back(MenuItem(cap, proc)); } inline void CMenu::AddSubMenu(const char* cap, callback_proc_ proc, int parent){ if(parent > menu_.size()) throw("Indice del menu mayor que lista del menu"); else menu_[parent].submenu_.push_back(MenuItem(cap, proc)); } inline void CMenu::PrintMenu(){ for(int i = 1; i < menu_.size(); ++i){ std::cout << i << ": " << menu_[i].caption_ << "\n"; for(int j = 0; j < menu_[i].submenu_.size(); ++j){ std::cout << " " << i * 10 + j + 1 << ": " << menu_[i].submenu_[j].caption_ << "\n"; } } std::cout << 0 << ": " << menu_[0].caption_<< "\n"; } inline void CMenu::DoMenu(){ int option = 0; int mainsize = menu_.size()-1; int msize = mainsize * 10 + menu_[mainsize].submenu_.size()+1; do{ while ((std::cout << "Eliga una Opcion: ") && (!(std::cin >> option) || option < 0 || option > menu_.size()*10)) { std::cout << "Opcion Invalida! "; std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); } int imenu = option / 10; int isubm = option % 10; if(option < 10 && option > 0 && option < menu_.size()){ if(menu_[option].proc_) menu_[option].proc_(); } else if(option >=11 && isubm != 0 && imenu < menu_.size()){ if(isubm <= menu_[imenu].submenu_.size()) if(menu_[imenu].submenu_[isubm-1].proc_) menu_[imenu].submenu_[isubm-1].proc_(); } else { std::cout << "Opcion Invalida \n"; } }while(option != 0);
teniendo void proc(void) podria ahora hacer Menu.AddMenu(proc); Pero lo que estoy tratando de hacer es algo como esto: int proc1(int x, int y); char* proc2(const char * strCh); Menu.AddMenu(proc1); //tipo incompatible Menu.AddMenu(proc2);
Ba, en realidad estoy pensando que tengo que guardar el tipo y la cantidad de argumentos algo asi como hace printf?
Título: Re: Puntero a funcion como argumento
Publicado por: ivancea96 en 10 Enero 2015, 14:59 pm
Si quieres una función con indeterminado número de argumentos: void func(int n, ...){} Los argumentos son contiguos en memoria a la primera variable. Obviamente, necesitas saber tipo y número de argumentos. Printf lo sabe buscando en la cadena los %.
Título: Re: Puntero a funcion como argumento
Publicado por: Yoel Alejandro en 10 Enero 2015, 16:25 pm
Sólo como un comentario, que me parece muy interesante el tema, una manera muy práctica de manejar menús.
Y por supuesto, la sugerencia de ivancea es la apropiada ;D para el problema planteado, es lo que se hace para manejar funciones con número variable de argumentos.
|