[Solucionado] std::thread error: invalid use of non-static member function

Iniciado por MeCraniDOS, 18 Abril 2015, 19:59 PM

0 Miembros y 1 Visitante están viendo este tema.

MeCraniDOS

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 (cpp) [Seleccionar]
std::vector <std::thread> th; //Hilos de ejecucion
std::vector <Padre*> padre; //Puntero a los hijos (Polimorfismo)


En el constructor de la clase hago esto

Código (cpp) [Seleccionar]
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 (cpp) [Seleccionar]
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 (cpp) [Seleccionar]
void bar(int x)
{
 // do stuff...
}

std::thread second (bar,0);


Lo que he intentado, me da error en la primera línea
Código (cpp) [Seleccionar]
th.at(0) = std::thread(padre.at(0)->moverHijo, parametros del metodo);
th.at(0).detach();

        error: invalid use of non-static member function

A ver si me podeis ayudar..  :-\

Un saludo y gracias
"La física es el sistema operativo del Universo"
     -- Steven R Garman

Eternal Idol

La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

MeCraniDOS

#2
Cita de: Eternal Idol en 18 Abril 2015, 22:36 PM
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 (cpp) [Seleccionar]
virtual int moverHijo(int retardo) = 0;

Y en las clases hijas hago esto
Código (cpp) [Seleccionar]
class Hijo : public virtual Padre
{
   public:

       // . . .

       int moverHijo(int retardo);


       // . . .
}


El error que me da es:

Código (cpp) [Seleccionar]
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 (cpp) [Seleccionar]
class Padre
{
   private:

       // Atributos

   public:

       // . . .

       virtual int moverHijo(int retardo) = 0;

       // . . .
};


Hijos (implementaciones del movimiento distintas)
Código (cpp) [Seleccionar]
class Hijo : public virtual Padre
{
   public:

       // . . .

       int moverHijo(int retardo);

       // . . .
};

Código (cpp) [Seleccionar]
class Hija : public virtual Padre
{
   public:

       // . . .

       int moverHijo(int retardo);

       // . . .
};


Donde se trabaja con las clases hijas
Código (cpp) [Seleccionar]
class Casa
{
   private:
       int retardo;

       std::vector <std::thread> th;
       std::vector <Padre*> padre; // Al ser una clase virtual, creo punteros a los hijos (polimorfismo)
       /** Ejemplo
          padre.push_back(new Hijo(parametros));
          padre.push_back(new Hija(parametros));
       */

       // . . .

   public:


       // . . .

       std::vector <int> iniciar();

       // . . .

};


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

Código (cpp) [Seleccionar]
std::vector <int> Casa::iniciar()
{
   // . . .

   for (unsigned int i = 0; i < padre.size(); i++)
   {
       th.at(i) = std::thread(padre.at(i)->moverHijo, retardo);
       th.at(i).detach();
   }

   // . . .
}


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

Un saludo
"La física es el sistema operativo del Universo"
     -- Steven R Garman

ivancea96

Creo que sería mejor que creases una función intermedia que haga un padre.moverHijo(). Algo como:

Código (cpp) [Seleccionar]
void func(int n){
    padre.moverHijo(int n);
}
//...
std::thread(&func, retardo).detach();


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

Código (cpp) [Seleccionar]
static void Hijo::moverHijo(Hijo& h, int retardo){
    h.moverHijo(retardo);
}


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.

MeCraniDOS

Cita de: 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 (cpp) [Seleccionar]
void func(int n){
    padre.moverHijo(int n);
}
//...
std::thread(&func, retardo).detach();


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

Código (cpp) [Seleccionar]
static void Hijo::moverHijo(Hijo& h, int retardo){
    h.moverHijo(retardo);
}


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 (cpp) [Seleccionar]
virtual int moverInterno(int retardo) = 0;

static int moverHijo(Padre &hijo, int retardo);

int Padre::moverHijo(Padre &hijo, int retardo)
{
    return hijo.moverInterno(retardo);
}


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


(Variables)
Código (cpp) [Seleccionar]
std::vector <std::thread> th;
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:
"La física es el sistema operativo del Universo"
     -- Steven R Garman