2012-01-19 9 views
35

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

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; 
} 

He intentado mirar hacia arriba en línea y todo lo que he podido encontrar es que no se puede tener un método virtual (puro o de otro tipo) en una clase normal, como esto:

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 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 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 virual de una clase debido a la naturaleza de "buscar y reemplazar" de las plantillas.

De todos modos, planteando la pregunta nuevamente en caso de que se haya perdido allí: ¿Se permiten funciones virtuales (puras o normales) dentro de una clase tempate?

+5

Parece que ya se haya descubierto la respuesta a esta ... –

+3

Como dije, lo juro por mí mismo que probado antes y tenía problemas. Cuando de repente funcionó, quería asegurarme de que no era solo porque estaba en un compilador diferente, diferentes banderas de advertencia/error, etc. y que estaba definido, preferiblemente, que estaba bien para el estándar. – Anthony

+2

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

Respuesta

44

Una plantilla de clase puede contener funciones virtuales virtuales o puras. Esto fue empleado por Andrei Alexandresu en "Modern C++ Design" para implementar el patrón de visitante usando plantillas y listas de tipos. Puede ver el código here in his Loki library si le interesa.

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 el vtable se puede conocer dentro de la unidad de traducción, por lo que se puede generar un vtable.

Como mencionaste, no puedes 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!

6

¿Se permiten funciones virtuales virtuales (puras o normales) dentro de una clase tempate?

Sí. Perfectamente legal.

6

Piensa 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 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, p. 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.

1

Una plantilla de clase con funciones virtuales es absolutamente buena. 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 le ayudaría a conseguir que:

//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; 
}; 
Cuestiones relacionadas