Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: MeCraniDOS en 18 Abril 2015, 19:59 pm



Título: [Solucionado] std::thread error: invalid use of non-static member function
Publicado por: MeCraniDOS en 18 Abril 2015, 19:59 pm
Hola  ;D,

Estoy teniendo problemas al crear un hilo  :-[

Tengo el siguiente código (simplificado a la parte donde me da error)


Atributos de la clase (Padre es una clase virtual)

Código
  1. std::vector <std::thread> th; //Hilos de ejecucion
  2. std::vector <Padre*> padre; //Puntero a los hijos (Polimorfismo)

En el constructor de la clase hago esto

Código
  1. padre.push_back(new HijoEjemplo(argumentos del constructor de hijo)); //Los vamos metiendo al final

Para acceder a sus métodos tengo que hacer esto:

Código
  1. padre.at(0)->moverHijo(parametros del metodo);

Ahora lo que estoy intentando hacer es ejecutar ese metodo en un hilo

Lo he intentado como hacen en este ejemplo pero me salta un error


Ejemplo (funcion, argumentos)
Código
  1. void bar(int x)
  2. {
  3.  // do stuff...
  4. }
  5.  
  6. std::thread second (bar,0);

Lo que he intentado, me da error en la primera línea
Código
  1. th.at(0) = std::thread(padre.at(0)->moverHijo, parametros del metodo);
  2. th.at(0).detach();
        error: invalid use of non-static member function

A ver si me podeis ayudar..  :-\

Un saludo y gracias


Título: Re: [?] std::thread error: invalid use of non-static member function
Publicado por: Eternal Idol en 18 Abril 2015, 22:36 pm
Hace el metodo estatico y en el parametro pasa el puntero al objeto.

https://foro.elhacker.net/programacion_cc/iquestcomo_accedo_a_this_desde_una_funcion_callback-t285522.0.html;msg1411745


Título: Re: [?] std::thread error: invalid use of non-static member function
Publicado por: MeCraniDOS en 19 Abril 2015, 11:51 am
Hace el metodo estatico y en el parametro pasa el puntero al objeto.

Me da error cuando intento hacer el método estático, he entendido el problema pero no se como lo puedo solucionar, en la clase padre tengo esto

Código
  1. virtual int moverHijo(int retardo) = 0;

Y en las clases hijas hago esto
Código
  1. class Hijo : public virtual Padre
  2. {
  3.    public:
  4.  
  5.        // . . .
  6.  
  7.        int moverHijo(int retardo);
  8.  
  9.  
  10.        // . . .
  11. }

El error que me da es:

Código
  1. static virtual int moverHijo(int retardo) = 0;
         error: member ‘moverHijo’ cannot be declared both virtual and static



La estructura de clases es la siguiente (quizá me habia explicado un poco mal)


Padre
Código
  1. class Padre
  2. {
  3.    private:
  4.  
  5.        // Atributos
  6.  
  7.    public:
  8.  
  9.        // . . .
  10.  
  11.        virtual int moverHijo(int retardo) = 0;
  12.  
  13.        // . . .
  14. };

Hijos (implementaciones del movimiento distintas)
Código
  1. class Hijo : public virtual Padre
  2. {
  3.    public:
  4.  
  5.        // . . .
  6.  
  7.        int moverHijo(int retardo);
  8.  
  9.        // . . .
  10. };
Código
  1. class Hija : public virtual Padre
  2. {
  3.    public:
  4.  
  5.        // . . .
  6.  
  7.        int moverHijo(int retardo);
  8.  
  9.        // . . .
  10. };

Donde se trabaja con las clases hijas
Código
  1. class Casa
  2. {
  3.    private:
  4.        int retardo;
  5.  
  6.        std::vector <std::thread> th;
  7.        std::vector <Padre*> padre; // Al ser una clase virtual, creo punteros a los hijos (polimorfismo)
  8.        /** Ejemplo
  9.            padre.push_back(new Hijo(parametros));
  10.            padre.push_back(new Hija(parametros));
  11.         */
  12.  
  13.        // . . .
  14.  
  15.    public:
  16.  
  17.  
  18.        // . . .
  19.  
  20.        std::vector <int> iniciar();
  21.  
  22.        // . . .
  23.  
  24. };

Lo que intento es ejecutar en un hilo, el método mover hijo

Código
  1. std::vector <int> Casa::iniciar()
  2. {
  3.    // . . .
  4.  
  5.    for (unsigned int i = 0; i < padre.size(); i++)
  6.    {
  7.        th.at(i) = std::thread(padre.at(i)->moverHijo, retardo);
  8.        th.at(i).detach();
  9.    }
  10.  
  11.    // . . .
  12. }

El error que me da al hacer esto es el del inicio del post..

Un saludo


Título: Re: [?] std::thread error: invalid use of non-static member function
Publicado por: ivancea96 en 19 Abril 2015, 14:57 pm
Creo que sería mejor que creases una función intermedia que haga un padre.moverHijo(). Algo como:

Código
  1. void func(int n){
  2.    padre.moverHijo(int n);
  3. }
  4. //...
  5. std::thread(&func, retardo).detach();
  6.  

También tienes otra opción, y es crear otro método del estilo:

Código
  1. static void Hijo::moverHijo(Hijo& h, int retardo){
  2.    h.moverHijo(retardo);
  3. }

O como sea tu código. El tema es que no puede ser virtual y static a la vez, cada uno tiene su significado. Static es una función o variable de clase que están adheridas a la clase en sí, no a sus objetos. No puede ser virtual una función que es static, como ya viste.


Título: Re: [?] std::thread error: invalid use of non-static member function
Publicado por: MeCraniDOS en 19 Abril 2015, 16:37 pm
Creo que sería mejor que creases una función intermedia que haga un padre.moverHijo(). Algo como:

Código
  1. void func(int n){
  2.    padre.moverHijo(int n);
  3. }
  4. //...
  5. std::thread(&func, retardo).detach();
  6.  

También tienes otra opción, y es crear otro método del estilo:

Código
  1. static void Hijo::moverHijo(Hijo& h, int retardo){
  2.    h.moverHijo(retardo);
  3. }

Con tu primera función tendría que pasarle tambien Hijo&, sino no puedo acceder a padre.

Prefiero utilizar la segunda opcion, me ha quedado de la siguiente manera:


Código
  1. virtual int moverInterno(int retardo) = 0;
  2.  
  3. static int moverHijo(Padre &hijo, int retardo);
  4.  
  5. int Padre::moverHijo(Padre &hijo, int retardo)
  6. {
  7.    return hijo.moverInterno(retardo);
  8. }

Pero al crear el hilo me sigue dando error...  :rolleyes:  (Supongamos que solo he creado un hijo)
Código
  1. th.at(0) = std::thread(Padre::moverHijo, padre.at(0), retardo);
  2. th.at(0).detach();

(Variables)
Código
  1. std::vector <std::thread> th;
  2. std::vector <Padre*> padre;

Error
Citar
||=== Build: Debug in Padre (compiler: GNU GCC Compiler) ===|
/usr/include/c++/4.9/functional||In instantiation of ‘struct std::_Bind_simple<int (*(Padre*, int))(Padre&, int)>’:|
/usr/include/c++/4.9/thread|140|required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = int (&)(Padre&, int); _Args = {Padre*&, int&}]’|
/home/**Ruta**/Casa.cpp|132|required from here|
/usr/include/c++/4.9/functional|1665|error: no type named ‘type’ in ‘class std::result_of<int (*(Padre*, int))(Padre&, int)>’|
/usr/include/c++/4.9/functional|1695|error: no type named ‘type’ in ‘class std::result_of<int (*(Padre*, int))(Padre&, int)>’|
||=== Build failed: 2 error(s), 3 warning(s) (0 minute(s), 0 second(s)) ===|

 :huh: :huh: