EDIT: RESOLVERmétodo virtual puro Llamado
Estoy trabajando en un proyecto multi-hilo en este momento en el que tengo una clase trabajadora de base, con diferentes clases de trabajadores que heredan de ella. En el tiempo de ejecución, las clases de trabajadores se convierten en hilos, que luego realizan el trabajo según sea necesario.
Ahora, tengo un Director que he escrito que se supone que debe mantener una serie de punteros a todos los trabajadores, para que pueda recuperar información de ellos, así como modificar las variables dentro de ellos más tarde.
me hicieron esto mediante la creación de un puntero a un puntero de la clase base:
baseWorkerClass** workerPtrArray;
A continuación, en el constructor del Director, que dinámicamente asignar una matriz de punteros a la clase trabajadora de base:
workerPtrArray = new baseWorkerClass*[numWorkers];
En el constructor de cada subproceso de trabajador, el trabajador invoca una función en el director que debe almacenar el puntero de ese trabajador en la matriz.
Así es como el director almacena los punteros:
Director::manageWorker(baseWorkerClass* worker)
{
workerPtrArray[worker->getThreadID()] = worker;
}
Aquí es un ejemplo de una variante del trabajador. Cada trabajador hereda de la clase de trabajador base, y la clase de trabajador base contiene funciones virtuales puras que deberían existir en todas las variantes de trabajador, así como algunas variables que se comparten entre todos los trabajadores.
class workerVariant : protected baseWorkerClass
{
public:
workerVariant(int id)
: id(id)
{
Director::manageWorker(this);
}
~workerVariant()
{
}
int getThreadID()
{
return id;
}
int getSomeVariable()
{
return someVariable;
}
protected:
int id;
int someVariable
};
Entonces el baseWorkerClass se ve algo como esto:
class baseWorkerClass
{
public:
baseWorkerClass()
{
}
~baseWorkerClass()
{
}
virtual int getThreadID() = 0;
virtual int getSomeVariable() = 0;
};
Después de cada variante trabajador se realiza la inicialización, debería terminar con una matriz de punteros a objetos baseWorkerClass. Esto significa que debería ser capaz de, por ejemplo, obtener el valor de una variable dada en un determinado trabajador utilizando su ID como el índice a la matriz, así:
workerPtrArray[5]->getSomeVariable(); // Get someVariable from worker thread 5
El problema es que este código provoca una accidente en un ejecutable de Windows, sin ninguna explicación de por qué, y en Linux, que dice:
método virtual pura llamada
terminar el arrendamiento llama sin excepción activa
abortada
Podría haber jurado que tenía esto funcionando en algún momento, así que estoy confundido sobre lo que he estropeado.
código sin modificar real que tiene el problema:
cabecera de la variante Trabajador: http://pastebin.com/f4bb055c8
Trabajador archivo de origen variante: http://pastebin.com/f25c9e9e3
cabecera de la clase trabajadora Base: http://pastebin.com/f2effac5
Base archivo fuente de la clase trabajadora: http://pastebin.com/f3506095b
Encabezado del director: http://pastebin.com/f6ab1767a
archivo director Fuente: http://pastebin.com/f5f460aae
EDIT: La información adicional, en la función manageWorker, me puede llamar a cualquiera de las funciones virtuales puras desde el puntero del "trabajador", y funciona muy bien. Fuera de la función manageWorker, cuando intento usar la matriz de punteros, falla.
EDIT: Ahora que lo pienso, el punto de entrada del hilo es operator(). El subproceso de Director se crea antes que los trabajadores, lo que puede significar que el operador de paréntesis sobrecargado llama funciones virtuales puras antes de que las clases secundarias puedan anularlas. Estoy investigando esto.
Gracias por la entrada. En realidad, sobre el método getThreadID, eso fue solo una inconsistencia de mi parte. Este no es el código real que estoy usando, solo son cosas que escribí hace unos minutos para ilustrar mi punto de forma clara y concisa. el método getThreadID _is_ pure virtual, y _is_ reemplazado en cada variante de trabajador. Todo lo que hace el método getThreadID es devolver la variable "id" del hilo. – jakogut
Cuando un objeto está en construcción (mientras se ejecuta el constructor), el mecanismo de función virtual nunca llamará a las funciones virtuales de una clase derivada del tipo del objeto. Esto se debe a que los constructores de las clases derivadas aún no se han ejecutado.Entonces, llamar a un método de clase derivado desde un constructor no funcionará. Una salida de esto es la construcción en dos fases, preferiblemente escondida detrás de un objeto envoltorio. (Lo mismo vale para la destrucción, por cierto.) – sbi
Oh, mierda, tienes razón, no pensé en eso. Déjame hacer una prueba rápida aquí, y te informaré. (Ahí va otra hora de sueño). – jakogut