• Viernes 8 de Noviembre de 2024, 19:19

Autor Tema:  PUNTERO A MÈTODO, problema  (Leído 1807 veces)

meyiyiyi

  • Nuevo Miembro
  • *
  • Mensajes: 11
    • Ver Perfil
PUNTERO A MÈTODO, problema
« en: Miércoles 30 de Junio de 2010, 09:14 »
0
TENGO LO SIGUIENTE
Busqueda.h:

Código: C++
  1. #ifndef CLASECITA_H_INCLUDED
  2. #define CLASECITA_H_INCLUDED
  3. #include "BinaryTree.cpp"
  4. class Busqueda{
  5.     private:
  6.     int x;
  7.     int y;
  8.  
  9.     public:
  10.     int getX();
  11.     void output2(int a);
  12. };
  13.  
  14. #endif // CLASECITA_H_INCLUDED
  15.  



Busqueda.cpp:

Código: C++
  1. #include <iostream>
  2. #include <string>
  3. #include "clasecita.h"
  4. #include "BinaryTree.cpp"
  5. using namespace std;
  6. #ifndef NULL
  7. #define NULL 0
  8. #endif
  9.  
  10. void output1(int a){
  11.     cout<<a;
  12. }
  13.  
  14. void Busqueda::output2(int a){
  15.     cout<<a;
  16. }
  17.  
  18.  int Busqueda::getX(){
  19.     return this->x;
  20.     BinTree<int> arbol;
  21.     arbol.SetInOrder(output1);
  22.     arbol.SetInOrder(output2); //Linea 21
  23.     arbol.InOrder();
  24. }
  25.  

Lo que tengo es una la clase Busqueda definida en el .h y desarrollada en el .cpp . Ademàs el .cpp tiene dos funciones las cuales se van a usar como parametro para un mètodo que requiere funciones como parametro. El tema es que cuando hago arbol.SetInOrder(output1) siendo output1 una funciòn desarrollada en ese mismo .cpp no tira error. Pero cuando hago arbol.SetInOrder(output2), siendo output2 un mètodo pùblico de la clase Busqueda, si tira el siguiente error:

Citar
Busqueda.cpp|21|error: no matching function for call to `BinTree<int>::SetInOrder(<unknown type>)'|

BinaryTree.cpp|173|note: candidates are: void BinTree<type>::SetInOrder(void (*)(type)) [with type = int]|

EL mètodo SetInOrder toma como parametro: void (*funcion) (type data)
Por què me permite pasarle a SetInOrder como parametro una funciòn de ese àmbito y no a su mètodo?.. Habia leido algo que para pasar un puntero de una funcion es distinto que pasar un puntero de un mètodo. Como lo hago entocnes?? MUCHAS GRACIAS!

diego.martinez

  • Miembro MUY activo
  • ***
  • Mensajes: 297
    • Ver Perfil
Re: PUNTERO A MÈTODO, problema
« Respuesta #1 en: Miércoles 30 de Junio de 2010, 11:06 »
0
buenas:

es por la convencion de llamadas.
Te explico, en C++ hay diferentes convenciones de llamada a la funcion que son stdcall y thiscall

la primera es la que se usa en las funciones normales y en los metodos estaticos (que funcionan igual).
la segunda es la que se usa en todos los demas métodos de una clase.

Al definir como una funcion (void output1(int a)) en Visual Studio el compilador automaticamente la define como stdcall (estandard).
Realmente es como si hubieras escrito "void __stdcall output1(int a)"
Las funciones standard envian sus parametros a la pila en orden.

Pero si la defines como un metodo de clase, se define como thiscall. Los metodos al fin y al cabo son como funciones, la  diferencia es que al llamarlos, el compilador automaticamente añade un parametro "extra" que es necesario en la programacion orientada a objetos.
 
La diferencia de estas convenciones de llamada es que las cdecl introducen el parametro "this" en el registro ECX,  para tener visibilidad de los miembros y metodos de la clase. Como el parametro adicional no se puede introducir sin un objeto que lo contextualize (ej: cuando haces miObj->UsarMetodo(parametro) ), no se puede usar el metodo directamente como un puntero. Este es un problema tipico de intentar usar un metodo como puntero o como thread.

La solucion?

a)podrias definir el metodo como estatico y usar singleton (o no usarlo si no necesitas acceso al objeto).
b)podrias definirlo como una funcion standard y pasar el this como parametro, en este caso quizas te convenga hacerla friend.
c) podrias usar functors (wikipedia)

suerte!  :good:

PD: editado para explicarlo un poco mejor.

PD: reañado , despues de documentarme mejor un segmento de codeproject

    __cdecl is the default calling convention for C and C++ programs. The advantage of this calling convetion is that it allows functions with a variable number of arguments to be used. The disadvantage is that it creates larger executables.
    __stdcall is used to call Win32 API functions. It does not allow functions to have a variable number of arguments.
    __fastcall attempts to put arguments in registers, rather than on the stack, thus making function calls faster.
    Thiscall calling convention is the default calling convention used by C++ member functions that do not use variable arguments.

meyiyiyi

  • Nuevo Miembro
  • *
  • Mensajes: 11
    • Ver Perfil
Re: PUNTERO A MÈTODO, problema
« Respuesta #2 en: Miércoles 30 de Junio de 2010, 17:44 »
0
Te agradezco enormemente la respuesta. A output2 la declarè como static:
Código: C++
  1.  
  2. class Busqueda{
  3.     private:
  4.     int x; //LINEA 6
  5.     int y;
  6.  
  7.     public:
  8.     int getX();
  9.     static void output2(int a);
  10. };
  11.  

Yo no lo habia puesto, ya que es un ejemplo del programa que estoy haciendo, pero desde output2 devo poder entrar a los miembros de la class Busqueda, serìa:

Código: C++
  1.  
  2. void Busqueda::output2(int a){
  3.     cout<<a;
  4.     x=15; //LINEA 16
  5. }
  6.  

Pero al ser static me tira el siguiente error:
Citar
Busqueda.h|6|error: invalid use of member `Busqueda::x' in static member function|

Busqueda.cpp|16|error: from this location|

GRACIAS OTRA VEZ!

meyiyiyi

  • Nuevo Miembro
  • *
  • Mensajes: 11
    • Ver Perfil
Re: PUNTERO A MÈTODO, problema
« Respuesta #3 en: Miércoles 30 de Junio de 2010, 17:47 »
0
Vos me dijiste de usar "singleton".. no se que es. OBvio que lo que estoy haciendo es buscar info sobre esto para entenderlo y poder usando; pero si me podes dar un ejemplo de como seria usar "singleton" en mi codigo te lo agradeceria ya q estoy muuy apurado para entregar el programa y me quedè trabado en esto.

diego.martinez

  • Miembro MUY activo
  • ***
  • Mensajes: 297
    • Ver Perfil
Re: PUNTERO A MÈTODO, problema
« Respuesta #4 en: Miércoles 30 de Junio de 2010, 19:37 »
0
buenas:

Enlace a wikipedia de singleton: http://es.wikipedia.org/wiki/Singleton

a ver, te pongo un ejemplo de las formas de hacerlo.

Cuando tu haces un miembro de una clase "static" este objeto se convierte en algo muy parecido a una global.

Código: C++
  1.  
  2. class PRU
  3. {
  4. public:
  5. static int MiValorGlobal;
  6. };
  7.  
  8.  

puedes acceder a MiValorGlobal usando el Contexto y luego el miembro.

PRU::MiValorGlobal

si por ejemplo usaras
Código: C++
  1.  
  2. class SINGLETON
  3. {
  4.  
  5. protected:
  6.     static SINGLETON * Instancia;
  7.    SINGLETON();
  8.  
  9. public:
  10.     static SINGLETON * GetInstance()
  11.     {
  12.      if (Instancia==0)
  13.          Instancia=new SINGLETON();
  14.  
  15.      return Instancia;
  16.     }
  17.  
  18. };
  19.  
  20.  

Si te fijas, no puedo acceder al constructor de la clase. No puedo hacer "new SINGLETON()". Sin embargo, hay un metodo "static" llamado GetInstance y un miembro static  llamado Instancia. Si llamo a SINGLETON::GetInstancia() la primera vez, me creará la instancia de la clase en el miembro estatico. El resto de las veces simplemente devolverá el contenido estatico de Instancia. Como esta protected, solo se puede acceder a traves de este metodo, y asi garantizamos que no se usa sin inicializarlo.
Ahora bien, cualquier modulo del programa que tenga visibilidad sobre la declaración de la clase podrá acceder a una Instancia unica y global del objeto.
Este metodo solo te sirve cuando va a haber un UNICO objeto de este tipo (como CHAL_LAYER, CAPPLICATION, CREGISTRY_CONTROL... etc).

Si necesitas multiples instancias de objetos que tengan un miembro o metodo para Threads  por ejemplo puedes poner como parametro el puntero al objeto y pasarlo manualmente.

Código: C++
  1.  
  2. class WORKER
  3. {
  4. public:
  5.      int WorkerId;
  6.      void Work();
  7.  
  8.      static void ThreadMethod(void *w)
  9.      {
  10.          WORKER * W=(WORKER*)w;
  11.          W->Work();
  12.      }
  13. };
  14.  
  15. BeginThread(WORKER::ThreadMethod,0,(void*)this);
  16.  
  17.  
  18.  

Y para los functors:
http://en.wikipedia.org/wiki/Function_object


:) suerte!

meyiyiyi

  • Nuevo Miembro
  • *
  • Mensajes: 11
    • Ver Perfil
Re: PUNTERO A MÈTODO, problema
« Respuesta #5 en: Viernes 2 de Julio de 2010, 01:16 »
0
Me da verguenza seguir sin entender. No me podès hacer el ejemplo con el còdigo q te pasè?..
(Es terrible la desesperaciòn q tengo.. pierdo la materia si no termino este tp)
IGual desde ya muchisimas gracias.

meyiyiyi

  • Nuevo Miembro
  • *
  • Mensajes: 11
    • Ver Perfil
Re: PUNTERO A MÈTODO, problema
« Respuesta #6 en: Viernes 2 de Julio de 2010, 01:22 »
0
Y me cuesta entender  el error del còdigo q enviè al principio. Pq a un mètodo x de una instancia, que recibe una funciòn como paràmetro, puedo pasarle una funciòn (en el ej output1) y no un metòdo (en el ej output2, miembro de Busqueda)??