2011-02-10 17 views
5
template <class T> 
class baseclass{ 
protected: 
    T data; 
public: 
    baseclass(){}; 
    void setData(T d); 
}; 

template<class T> 
void baseclass<T>::setT(T d){ 
    data = d; 
} 

Se muestra arriba mi clase de base, una variable de miembro protegida, un establecedor.Problema de herencia de plantilla simple C++

template <class T> 
class aclass : public baseclass<T> 
{ 
    public: 
     aclass(T d); 
}; 

template<class T> 
aclass<T>::aclass(T d){ 
    setData(d); <---WORKS 
    data = d; <---DOESN'T WORK 
} 

Ahora esta es mi subclase de la primera. Por alguna razón, acceder directamente a la variable miembro protegida no funciona, aunque creo que debería hacerlo. Sin embargo, acceder al colocador funciona bien. Soy un novato con C++, estoy seguro de que me falta algo obvio.

+0

¿Funciona si escribe esto-> data = d ;? –

+0

¿Podrías por favor ser más específico de lo que significa "no funciona"? ¿Estás obteniendo un error de compilación (y si es así, cuál), o no hace nada en tiempo de ejecución o qué? –

+0

@Michael sí, lo hace. naturalmente. – jakev

Respuesta

8

La razón por la que esto no funciona es una peculiaridad en la forma en que las plantillas de C++ dan nombre a la resolución. En particular, si tiene una clase de plantilla que hereda de otra clase que depende de un tipo de plantilla (como lo está haciendo en este caso), no puede acceder directamente a los miembros de esa clase base sin darle al compilador una pista sobre dónde Mira. Esta es la causa del error que está recibiendo.

Para solucionar esto, se puede reescribir su constructor como

template<class T> 
aclass<T>::aclass(T d){ 
    setData(d); 
    this->data = d; 
} 

Ahora que el compilador sabe que data de alguna manera debe ser un miembro de aclass<T>, se puede encontrar lo que está buscando.

Curiosamente, también debería recibir un error en la línea anterior por el mismo motivo. No estoy seguro de por qué decidió compilar. Para solucionar este problema, puede hacer esto:

template<class T> 
aclass<T>::aclass(T d){ 
    this->setData(d); 
    this->data = d; 
} 

Alternativamente, se puede añadir una declaración using para decirle al compilador que aclass hereda el método setData de su clase padre. En la declaración de la clase, considere agregar esta línea:

template <class T> 
class aclass : public baseclass<T> 
{ 
    public: 
     aclass(T d); 

     using baseclass<T>::setData; 
}; 

Al igual que el this-> para los miembros de datos, este truco hace que sea inequívoco donde el nombre proviene de setData y ayuda a que el compilador sabe lo que está hablando.

Espero que esto ayude!

+0

Muy útil, gracias. – jakev

+1

El setData (d) funciona porque d depende del parámetro de la plantilla. Por lo tanto, no se resuelve hasta que se conozca T. En ese momento, también sabemos la clase base real. –

+0

http://www.parashift.com/c++-faq-lite/templates.html#faq-35.19 – jakev

Cuestiones relacionadas