Programación General > C/C++
PUNTERO A MÈTODO, problema
meyiyiyi:
TENGO LO SIGUIENTE
Busqueda.h:
--- Código: C++ ---#ifndef CLASECITA_H_INCLUDED#define CLASECITA_H_INCLUDED#include "BinaryTree.cpp"class Busqueda{ private: int x; int y; public: int getX(); void output2(int a);}; #endif // CLASECITA_H_INCLUDED
Busqueda.cpp:
--- Código: C++ ---#include <iostream>#include <string>#include "clasecita.h"#include "BinaryTree.cpp"using namespace std;#ifndef NULL#define NULL 0#endif void output1(int a){ cout<<a;} void Busqueda::output2(int a){ cout<<a;} int Busqueda::getX(){ return this->x; BinTree<int> arbol; arbol.SetInOrder(output1); arbol.SetInOrder(output2); //Linea 21 arbol.InOrder();}
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]|
--- Fin de la cita ---
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:
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:
Te agradezco enormemente la respuesta. A output2 la declarè como static:
--- Código: C++ --- class Busqueda{ private: int x; //LINEA 6 int y; public: int getX(); static void output2(int a);};
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++ --- void Busqueda::output2(int a){ cout<<a; x=15; //LINEA 16}
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|
--- Fin de la cita ---
GRACIAS OTRA VEZ!
meyiyiyi:
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:
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++ --- class PRU{public:static int MiValorGlobal;};
puedes acceder a MiValorGlobal usando el Contexto y luego el miembro.
PRU::MiValorGlobal
si por ejemplo usaras
--- Código: C++ --- class SINGLETON{ protected: static SINGLETON * Instancia; SINGLETON(); public: static SINGLETON * GetInstance() { if (Instancia==0) Instancia=new SINGLETON(); return Instancia; } };
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++ --- class WORKER{public: int WorkerId; void Work(); static void ThreadMethod(void *w) { WORKER * W=(WORKER*)w; W->Work(); }}; BeginThread(WORKER::ThreadMethod,0,(void*)this);
Y para los functors:
http://en.wikipedia.org/wiki/Function_object
:) suerte!
Navegación
[#] Página Siguiente
Ir a la versión completa