El problema superficial es que llama a una función virtual que aún no se conoce (los objetos se construyen de padres a hijos, así también lo son los vtables). Tu compilador te advirtió acerca de eso.
El problema esencial, que yo sepa, es que intenta reutilizar la funcionalidad por herencia. Esto es casi siempre una mala idea. Un problema de diseño, por así decirlo :)
Esencialmente, usted intenta crear instancias de un patrón Template Method, para separar el lo del cuando: leer primero algunos datos (de alguna manera), y luego procesarlo (en de alguna manera).
Esto probablemente funcionará mucho mejor con la agregación: dé la función de procesamiento al método de la plantilla para que se llame en el momento adecuado. Tal vez incluso puedas hacer lo mismo con la funcionalidad de lectura.
La agregación se puede hacer de dos maneras:
- Uso de las funciones virtuales (es decir,Runtime Encuadernación)
- Uso de plantillas (es decir, tiempo de compilación Encuadernación)
Ejemplo 1: tiempo de ejecución de unión
class Data {};
class IReader { public: virtual Data read() = 0; };
class IProcessor { public: virtual void process(Data& d) = 0; };
class ReadNProcess {
public:
ReadNProcess(IReader& reader, IProcessor processor){
processor.process(reader.read());
}
};
Ejemplo 2: tiempo de compilación obligatorio
template< typename Reader, typename Writer > // definitely could use concepts here :)
class ReadNProcess {
public:
ReadNProcess(Reader& r, Processor& p) {
p.process(r.read());
}
};
Correcto, pero algo corto. Al menos debe copiar la conclusión: "Cosas para recordar: no invoque funciones virtuales durante la construcción o la destrucción, porque tales llamadas nunca irán a una clase más derivada que la del constructor o destructor actualmente en ejecución". – paercebal
Aún así, realmente creo que deberías pensar dos veces antes de mezclar la funcionalidad por herencia. En mi humilde opinión, esta pregunta muestra un flujo de diseño debajo de la superficie. – xtofl