¿Se permiten métodos virtuales puros dentro de una clase de plantilla?

4 minutos de lectura

Una vez antes, estaba seguro de que no podías hacer esto, pero el otro día estaba jugando con un código y parecía compilar y funcionar. Solo quiero verificar que no solo estoy teniendo suerte. ¿Puede una clase de plantilla tener una función virtual pura, lo que supongo que también significaría que los métodos virtuales simples también serían válidos para el destructor?

template <typename WordType> class DataSource
{
public:
    DataSource();
    DataSource(DataSource const& other);
    virtual ~DataSource();

    virtual void Put(
        WordType const* const data,
        unsigned int const wordCount) = 0;
}

Intenté buscarlo en línea y todo lo que pude encontrar es que no puede tener un método virtual (puro o no) en una clase normal como esta:

class DataSource
{
public:
    DataSource();
    DataSource(DataSource const& other);
    virtual ~DataSource();

    template <typename WordType>
    virtual void Put(
        WordType const* const data,
        unsigned int const wordCount) = 0;
}

Y que esto se debe a la imposibilidad de administrar una tabla virtual para hacer referencia a todos los diferentes tipos de tipos posibles con los que se instanciaría este método.

Sin embargo, cuando se trata de una función de miembro virtual de una clase de plantilla, parece ser diferente porque toda la clase en sí misma se “crea” a través del parámetro de plantilla cuando se instancia la variable de clase de plantilla. En este punto, el método virtual es como cualquier otro método virtual de una clase debido a la naturaleza de “buscar y reemplazar” de las plantillas.

De todos modos, volviendo a plantear la pregunta en caso de que se pierda allí: ¿Se permiten funciones virtuales virtuales (puras y/o normales) dentro de una clase de plantilla?

  • Parece que ya has averiguado la respuesta a esto…

    –Oliver Charlesworth

    19 de enero de 2012 a las 0:36

  • Como dije, me juro a mí mismo que lo probé antes y tuve problemas. Cuando de repente funcionó, quería asegurarme de que no era solo porque estaba en un compilador diferente, diferentes indicadores de advertencia / error, etc. y que estaba definido, preferiblemente, que estaba bien según el estándar.

    – Antonio

    19 de enero de 2012 a las 0:40

  • Además, por lo que vale, no pude encontrar nada en línea que dijera definitivamente de una forma u otra. ¿Qué mejor lugar para poner esta información que SO?

    – Antonio

    19 de enero de 2012 a las 0:41

  • posible duplicado de ¿Es seguro si una plantilla contiene una función virtual? y plantillas y funciones virtuales en C++? permitió ?

    – Greg Hewgill

    19 de enero de 2012 a las 1:02


avatar de usuario
templatetypedef

De hecho, una plantilla de clase puede contener funciones virtuales o virtuales puras. Esto fue empleado por Andrei Alexandresu en “Modern C++ Design” para implementar el patrón de visitantes usando plantillas y listas de tipos. Puedes ver el código aquí en su biblioteca Loki si estás interesado

Con la mayoría de las implementaciones estándar de C++, esto está bien, porque cuando se crea una instancia de la plantilla, la función virtual termina siendo una sola función. En consecuencia, el número de ranuras necesarias en la tabla v se puede conocer dentro de la unidad de traducción, por lo que se puede generar una tabla v.

Como mencionó, no puede tener una función de miembro de plantilla virtual porque la cantidad de ranuras de vtable no se conocería dentro de la unidad de traducción.

¡Espero que esto ayude!

¿Se permiten funciones virtuales virtuales (puras y/o normales) dentro de una clase de plantilla?

Sí. Perfectamente legal.

Piense en qué es una clase de plantilla: no es una clase en sí misma, sino una plantilla que el compilador puede usar para crear clases.

Como tal, no hay ninguna razón por la que no pueda incluir una función virtual (pura o no) en la definición de la clase de plantilla, porque eso, en sí mismo, no genera ningún código, incluida la tabla virtual.

Cuando realmente instanciamos la clase de plantilla, por ejemplo DataSource<int>entonces el compilador solo necesita construir la tabla virtual para ese tipo seleccionado, por lo que no es diferente de una función virtual (pura o no) para una clase sin plantilla.

Una plantilla de clase con funciones virtuales está absolutamente bien. Sin embargo, no se permiten las funciones de plantilla con la palabra clave virtual con el prefijo en una clase o clase de plantilla. A continuación te ayudaría a conseguir eso:

//This is perfectly fine.
template <type T>
class myClass{
     virtual void function() = 0;
};

//This is NOT OK...
template<type T>
class myClass{
      template <type T>
      virtual void function() = 0;
};

¿Ha sido útil esta solución?