2011-09-12 16 views
5

duplicado de: "pure virtual method called" when implementing a boost::thread wrapper interfacehilo impulso destruye polimorfismo

Estoy tratando de crear una versión más orientada a objetos de los hilos que utilizan hilos de impulso.

así que creé una clase Thread:

class Thread { 
public: 
    Thread() {} 
    virtual ~Thread() { thisThread->join(); } 

    void start() { thisThread = new boost::thread(&Thread::run, this); } 

    virtual void run() {}; 

private: 
    boost::thread *thisThread; 
}; 

esta clase crea el hilo de inicio() así:

thisThread = new boost::thread(&Thread::run, this);

El problema es que cuando se crea una clase que sobrescribe el método run(), el método run() de Subproceso se llama por el subproceso en lugar del nuevo run() método

Por ejemplo, tengo una clase que se extiende Tema:

class CmdWorker: public Thread { 
public: 
    CmdWorker() : Thread() {} 
    virtual ~CmdWorker() {} 

    void run() { /* deosn't get called by the thread */ } 
}; 

cuando lo haga

Thread *thread = new CmdWorker(); 
thread.start(); //---> calls run() from Thread instead of run() from CmdWorker 

pero sólo para ser más claro:

thread.run(); calls the correct run from CmdWorker, (run() is virtual from Runnable) 

Alguna idea de por qué sucede esto o ¿Cómo se puede arreglar?

NOTA: creé una función (que no tiene nada que ver con la clase Thread)

void callRun(Thread* thread) { 
    thread->run(); 
} 

y cambió la creación del hilo a:

thisThread = new boost::thread(callRun, this); 

al depurar me di cuenta de que el thread el puntero apunta a un objeto de tipo Thread en lugar de CmdWorker

EDIT:

código

caso_prueba en: http://ideone.com/fqMLF y http://ideone.com/Tmva1

objeto parece estar en rodajas (pero esto es extraño, ya que se utilizan punteros)

no lograron añadir impulso a ella

+0

¡La pregunta no está clara para mí! – Nawaz

+1

No hay suficiente código. No veo cómo usarías tal construcción. –

+2

FYI 'std :: thread' está llegando. ¿Qué es exactamente lo que está mal con 'boost :: thread' de todos modos? – spraff

Respuesta

1

Haciendo &Thread::Run en una función no virtual, está forzando a cualquier clase que se deriva de Thread a usar la función especificada en la clase de base Thread. Intenta hacer Thread :: Run un vacío virtual y ve si eso soluciona tu problema.

+1

run es virtual desde Runnable – Ha11owed

+0

pero no desde Thread. – Michael

+3

@Michael: en C++, 'virtual' se hereda de la clase base siempre que las firmas de función miembro coincidan (lo que hacen en este caso); declarar 'Thread :: run' como' virtual' sería redundante. – ildjarn

3

al depurar me di cuenta de que el indicador de paso está apuntando a un objeto de hilo tipo en lugar de CmdWorker

Tal vez se corta el objeto CmdWorker (es decir, copiado por valor) en un objeto Thread en algún lugar de ¿tu codigo?

¿Obtiene el mismo comportamiento con una funda de prueba mínima?

+0

sí Obtengo el mismo comportamiento con un testcase – Ha11owed

2

Al leer sus actualizaciones, está llamando a eliminar en el hilo principal, mientras que el hilo está comenzando en el otro. Dependiendo de la carrera entre el destructor y la invocación de run, se podrá:

  1. Crash antes de que comience, porque la viable es destruido por completo
  2. Llame al hilo :: run (que es puro virtual y accidentes con un golpe seco virtual pura)
  3. Llame a la función correcta, que es el plazo clase derivada()

Si se agrega una llamada a sleep(1) después de llamar comienzo, pero antes de llamar delete, podrás encontrar que funciona un s esperas

+0

Simplifiqué el ejemplo y eliminé cualquier bloqueos + comprobaciones. también en el destructor Hago un join() así que espera a que termine el hilo. como mencioné antes de ejecutar run() from thread. – Ha11owed

+3

@ Ha11owed Si agrega una combinación en el destructor de 'Thread', cuando se llame a join, la clase más derivada ya se habrá destruido y las entradas de vtable para ella ya no existen. –

+0

Entiendo ahora no noté que – Ha11owed