2010-09-26 122 views
16

soy un nuevo programador en C++. y estoy usando plantillas por primera vez.herencia de plantilla C++

tengo una clase abstracta y otra clase que la amplía. pero todos los miembros protected de la clase abstracta no son reconocidos por la otra clase:

class0.h:

template<class T> 
class class0 { 

protected: 
    char p; 
public: 
    char getChar(); 
}; 

**class1.h** 
template<class T> 
class class1:public class0<T> { 
public: 
    void printChar(); 
}; 
template<class T> 
void class1<T>::printChar(){ 
    cout<< p<<endl;//p was not declared in this scope 
} 

gracias. tener una gran semana =)

+0

Sus clases base necesitan un destructor virtual público o un destructor no virtual protegido/privado. – GManNickG

+0

BTW, ¿qué clase es abstracta en esto? – Chubsdad

Respuesta

26

La razón por la que esto está sucediendo tiene que ver con las reglas de búsqueda para las plantillas.

p no es una expresión dependiente porque es solo un identificador y no algo que depende del parámetro de la plantilla. Esto significa que las clases base que dependen del parámetro de la plantilla no se buscarán para resolver el nombre p. Para solucionar este problema, debe usar algo que no dependa del parámetro de la plantilla. Usar this-> hará esto.

p. Ej.

cout << this->p << endl; 
+0

¡Gracias! eso ayudó =) tener un buen día! – yonka

+3

@yonka: Deberías aceptar su respuesta. – GManNickG

+0

@GMan: No lo sé; litb ha publicado una respuesta ahora. :-) –

2

No obtengo ese error de compilación en VC9. Sin embargo, hay varios problemas con el código: en primer lugar, no necesita ser una clase de plantilla, ya que está escrito actualmente ... ¿pero tal vez simplemente lo simplificó para esta pregunta? En segundo lugar, la clase base debe tener un destructor virtual.

#include <iostream> 

using namespace std; 

class class0 { 
public: 
    virtual ~class0(){} 

protected: 
    char p; 
public: 
    char getChar(); 
}; 

class class1 : public class0 { 
public: 
    void printChar(); 
}; 

void class1::printChar(){ 
    cout << p << endl;//p was not declared in this scope 
} 

int main() { 
    class1 c; 
    c.printChar(); 
    return 1; 
} 

Puesto que usted está aprendiendo acerca de las plantillas, sugeriría no mezclar conceptos (herencia & plantillas) mientras se aprende. Empezar con un ejemplo sencillo como esto ...

#include <iostream> 
#include <string> 

using namespace std; 

template <typename T> 
T add(const T& a, const T& b) { 
    return a + b; 
} 

int main() { 
    int x = 5; 
    int y = 5; 

    int z = add(x, y); 
    cout << z << endl; 

    string s1("Hello, "); 
    string s2("World!"); 

    string s3 = add(s1, s2); 
    cout << s3 << endl; 

    return 1; 
} 

El concepto importante en el código anterior es que escribimos UNO función que sepa sumar enteros y cadenas (y muchos otros tipos para el caso).

+4

¿Por qué debería la clase base tener un destructor virtual? Las plantillas a menudo se utilizan para implementar el polimorfismo paramétrico, y la eliminación virtual solo es útil para el polimorfismo dinámico (y solo si la eliminación se realiza de forma polimórfica). –

+1

Se sabe que el compilador de Visual Studio 2008 no implementa correctamente las reglas de búsqueda de plantilla en este caso. Es por eso que no ves el error. –

+0

@Ben Voigt, buen punto, pero el OP acaba de comenzar con plantillas y supongo que probablemente aún no lo hayan cubierto. Pero parece que han cubierto la herencia y, a menos que busque polimorfos en tiempo de compilación, lo más seguro es virtualizar el destructor base. – dgnorton

14

Para un nombre que se alzó en una clase base dependientes, dos condiciones deben ser satisfechos

  • Es necesaria que la búsqueda no está calificado
  • Es necesaria que el nombre es dependiente

Estas reglas como se indica en C++ 03 son diferentes de rules stated by unrevised C++98, donde satisface la segunda viñeta (haciendo un nombre dependiente) fue suficiente para encontrar nombres declarados en clases base dependientes.

Se busca un nombre dependiente en el momento de creación de instancias y una búsqueda que no sea búsqueda no calificada no ignorará las clases base dependientes. Ambas condiciones deben cumplirse para encontrar un nombre declarado en una clase base dependiente, ninguno de ellos es suficiente.Para satisfacer ambas condiciones se pueden utilizar diversas construcciones

this->p 
class1::p 

ambos nombres p son dependientes y la primera versión utiliza el acceso miembro de la clase de búsqueda y la segunda versión utiliza nombre calificado de búsqueda.