elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Usando Git para manipular el directorio de trabajo, el índice y commits (segunda parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Puntero a funcion como argumento
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Puntero a funcion como argumento  (Leído 2,589 veces)
_Enko


Desconectado Desconectado

Mensajes: 538



Ver Perfil WWW
Puntero a funcion como argumento
« 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:
Código
  1. void proc1(void){
  2.    std::cout << "proc1" << std::endl;
  3. }
  4. void proc1a(void){
  5.    std::cout << "proc1a" << std::endl;
  6. }
  7. void proc1b(void){
  8.    std::cout << "proc1b" << std::endl;
  9. }
  10. void proc2(void){
  11.    std::cout << "proc 2" << std::endl;
  12. }
  13.  
  14. void proc3a(void){
  15.    std::cout << "proc 3a" << std::endl;
  16. }
  17. void proc3b(void){
  18.    std::cout << "proc 3b" << std::endl;
  19. }
  20. void proc3c(void){
  21.    std::cout << "proc 3c" << std::endl;
  22. }
  23.  
  24.  
  25.  
  26. int main(int argc, char* argv[]){
  27.    CMenu menu;
  28.    menu.AddMenu("OPCION 1", proc1);
  29.    menu.AddSubMenu("OPCION1A", proc1a, 1); //submenu de la opcion 1
  30.    menu.AddSubMenu("OPCION1B", proc1b, 1);
  31.    menu.AddMenu("OPCION 2", proc2);
  32.    menu.AddMenu("OPCION 3", NULL); //opcion 3 separador, no tendria funcion
  33.    menu.AddSubMenu("OPCION3A",  proc3a, 3); //submenu de la opcion 3
  34.    menu.AddSubMenu("OPCION3B", proc3b, 3);
  35.    menu.AddSubMenu("OPCION3C", proc3c, 3);
  36.    menu.PrintMenu();
  37.    menu.DoMenu();
  38.    return 0;
  39. }
  40.  

El resultado es algo asi:
Citar
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:
Código
  1. typedef void(*callback_proc_)(void);
  2. inline void CMenu::AddMenu(const char* cap, callback_proc_ proc){
  3.  

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


En línea

ivancea96


Desconectado Desconectado

Mensajes: 3.412


ASMático


Ver Perfil WWW
Re:
« Respuesta #1 en: 9 Enero 2015, 22:47 pm »

Conviértelo a void*.


En línea

_Enko


Desconectado Desconectado

Mensajes: 538



Ver Perfil WWW
Re: Puntero a funcion como argumento
« Respuesta #2 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.

Código
  1. #include <vector>
  2. #include <string>
  3. #include <iostream>
  4.  
  5.  
  6. typedef void(*callback_proc_)(void);
  7. class CMenu;
  8.  
  9.  
  10. class MenuItem{
  11.    public:
  12.        MenuItem(const char* cap, callback_proc_ proc):caption_(cap),proc_(proc){}
  13.        ~MenuItem(){
  14.            submenu_.clear();
  15.        }
  16.        friend class CMenu;
  17.    private:
  18.        callback_proc_ proc_;
  19.        std::string caption_;
  20.        std::vector<MenuItem> submenu_;
  21. };
  22.  
  23. class CMenu{
  24. public:
  25.    inline void AddMenu(const char* cap, callback_proc_ proc);
  26.    inline void AddSubMenu(const char* cap, callback_proc_ proc, int parent);
  27.    inline void PrintMenu();
  28.    inline void DoMenu();
  29.    CMenu();
  30.    ~CMenu();
  31.  
  32. private:  
  33.     std::vector<MenuItem> menu_;
  34. };
  35.  
  36. CMenu::CMenu(){
  37.    menu_.push_back(MenuItem("SALIR", NULL));
  38.  
  39. }
  40.  
  41. CMenu::~CMenu(){
  42.    for(int i = 1; i < menu_.size(); ++i){
  43.        menu_[i].submenu_.clear();
  44.    }
  45.    menu_.clear();
  46. }
  47.  
  48. inline void CMenu::AddMenu(const char* cap, callback_proc_ proc){
  49.    menu_.push_back(MenuItem(cap, proc));
  50.  
  51. }
  52. inline void CMenu::AddSubMenu(const char* cap, callback_proc_ proc, int parent){
  53.    if(parent > menu_.size())
  54.        throw("Indice del menu mayor que lista del menu");
  55.    else
  56.        menu_[parent].submenu_.push_back(MenuItem(cap, proc));
  57. }
  58.  
  59. inline void CMenu::PrintMenu(){
  60.    for(int i = 1; i < menu_.size(); ++i){
  61.        std::cout << i << ": " << menu_[i].caption_ << "\n";
  62.        for(int j = 0; j < menu_[i].submenu_.size(); ++j){
  63.            std::cout << "   " << i * 10 + j + 1 << ": " <<  menu_[i].submenu_[j].caption_ << "\n";
  64.        }
  65.    }  
  66.    std::cout << 0 << ": " << menu_[0].caption_<< "\n";
  67. }
  68.  
  69. inline void CMenu::DoMenu(){
  70.    int option = 0;
  71.    int mainsize = menu_.size()-1;
  72.    int msize = mainsize * 10 + menu_[mainsize].submenu_.size()+1;
  73.    do{
  74.        while ((std::cout << "Eliga una Opcion: ") && (!(std::cin >> option) || option < 0 || option > menu_.size()*10)) {
  75.            std::cout << "Opcion Invalida! ";
  76.            std::cin.clear();
  77.            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
  78.        }
  79.  
  80.        int imenu = option / 10;
  81.        int isubm = option % 10;
  82.        if(option < 10 && option > 0 && option < menu_.size()){
  83.            if(menu_[option].proc_)
  84.                menu_[option].proc_();
  85.        } else if(option >=11 && isubm != 0 && imenu < menu_.size()){
  86.            if(isubm <= menu_[imenu].submenu_.size())
  87.                if(menu_[imenu].submenu_[isubm-1].proc_)
  88.                    menu_[imenu].submenu_[isubm-1].proc_();
  89.        } else {
  90.            std::cout << "Opcion Invalida \n";
  91.        }
  92.    }while(option != 0);
  93.  
  94.  
  95.  

teniendo  void proc(void) podria ahora hacer
Menu.AddMenu(proc);

Pero lo que estoy tratando de hacer es algo como esto:
Código:
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?
En línea

ivancea96


Desconectado Desconectado

Mensajes: 3.412


ASMático


Ver Perfil WWW
Re: Puntero a funcion como argumento
« Respuesta #3 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 %.
« Última modificación: 10 Enero 2015, 16:12 pm por ivancea96 » En línea

Yoel Alejandro

Desconectado Desconectado

Mensajes: 254



Ver Perfil WWW
Re: Puntero a funcion como argumento
« Respuesta #4 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.
En línea

Saludos, Yoel.
P.D..-   Para mayores dudas, puedes enviarme un mensaje personal (M.P.)
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines