2011-07-06 13 views
23

I tienen los siguientes 4 archivos heredado:plantillas: variables miembro de la clase padre no visibles en la clase

  1. arrayListType.h: declarar y definir arrayListType clase como una plantilla
  2. unorderedArrayListType.h: hereda de arrayListType clase y declara y define unorderedArrayListType como plantilla.
  3. main1.cpp: Programa de prueba para probar la clase unorderedArrayListType.
  4. Makefile

me sale un error de compilación diciendo cuando se accede a las variables protegidas de arrayListType en unorderedArrayListType por ejemplo: "longitud no declarado en este ámbito", "lista no declarado en este ámbito", donde la longitud y la lista son variables protegidas en la clase arrayListType.

Los siguientes son los códigos:
arrayListType.h

#ifndef H_arrayListType 
#define H_arrayListType 

#include <iostream> 

using namespace std; 

template <class elemType> 
class arrayListType 
{ 

public: 

    const arrayListType<elemType>&operator=(const arrayListType<elemType>&); 

    bool isEmpty() const; 
    bool isFull() const; 
    int listSize() const; 
    int maxListSize() const; 
    void print() const; 
    bool isItemAtEqual(int location, const elemType& item) const; 
    virtual void insertAt(int location, const elemType& insertItem) = 0; 
    virtual void insertEnd(const elemType& insertItem) = 0; 
    void removeAt(int location); 
    void retrieveAt(int location, elemType& retItem) const; 
    virtual void replaceAt(int location, const elemType& repItem) = 0; 
    void clearList(); 
    virtual int seqSearch(const elemType& searchItem) const; 
    virtual void remove(const elemType& removeItem) = 0; 

    arrayListType(int size = 100); 
    arrayListType(const arrayListType<elemType>& otherList); 

    virtual ~arrayListType(); 


protected: 

    elemType *list; 
    int length; 
    int maxSize; 
}; 


template <class elemType> 
bool arrayListType<elemType>::isEmpty() const 
{ 
    return (length == 0); 
} 

// remaining non-virtual functions of arrayListType class 

#endif 

unorderedArrayListType.h

#ifndef H_unorderedArrayListType 
#define H_unorderedArrayListType 

//#include <iostream> 
#include "arrayListType.h" 

//using namespace std; 

template <class elemType> 
class unorderedArrayListType: public arrayListType<elemType> 
{ 

public: 

    void insertAt(int location, const elemType& insertItem); 
    void insertEnd(const elemType& insertItem); 
    void replaceAt(int location, const elemType& repItem); 
    int seqSearch(const elemType& searchItem) const; 
    void remove(const elemType& removeItem); 

    unorderedArrayListType(int size = 100); 
}; 

template <class elemType> 
void unorderedArrayListType<elemType>::insertAt(int location, const elemType& insertItem) 
{ 
    for(int i = length; i > location; i--) 
     list[i] = list[i - 1]; 

    list[location] = insertItem; 
    length++; 
} 

// Remaining virtual functions that need to be defined by the inherited class 

#endif 

main1.cpp

#include <iostream> 
#include "unorderedArrayListType.h" 

using namespace std; 


int main() 
{ 
    unorderedArrayListType<int> intList(25); 

    int number; 
    cout<<"Line 3: Enter 8 integers: "; 

    for(int count = 0; count < 8; count++) 
    { 
     cin>>number; 
     intList.insertEnd(number); 
    } 

    cout<<"Line 8: intList: "; 
    intList.print(); 
    cout<<endl; 
} 

Makefile:

all: main1 


main1.o: main1.cpp 
    g++ -c -Wall main1.cpp 

main1: main1.o 
    g++ -Wall main1.o -o main 


clean: 
    rm -f *.o *~ main1 

El siguiente es el error de compilación:

make 
g++ -c -Wall main1.cpp 
In file included from main1.cpp:2: 
unorderedArrayListType.h: In member function 'void unorderedArrayListType<elemType>::insertAt(int, const elemType&)': 
unorderedArrayListType.h:30: error: 'length' was not declared in this scope 
unorderedArrayListType.h:31: error: 'list' was not declared in this scope 
unorderedArrayListType.h:33: error: 'list' was not declared in this scope 

más funciones de unorderedArrayListType variables enumeradas y protegidas indicados como no declarado en el ámbito de aplicación. Preguntándose cuál podría ser el error.

Nueva error:

make 
g++ -Wall main1.o -o main 
Undefined      first referenced 
symbol        in file 
arrayListType<int>::seqSearch(int const&) constmain1.o 
ld: fatal: Symbol referencing errors. No output written to main 
collect2: ld returned 1 exit status 
*** Error code 1 
make: Fatal error: Command failed for target `main1' 
+1

posible duplicado de [¿Por qué tengo que acceder a los miembros de la clase base de la plantilla a través de este puntero?] (Http://stackoverflow.com/questions/4643074/why-do-i-have-to-access-template- base-class-members-through-the-puntero) – Pradhan

Respuesta

47

Esto se debe a la plantilla primaria de una clase de plantilla no se crea una instancia durante el paso de compilación que examina primero la plantilla. Estos nombres parecen no depender de la creación de instancias de la plantilla en particular y, por lo tanto, las definiciones deben estar disponibles. (Si nunca mira a la definición de arrayListType, a continuación, la lectura del código de unorderedArrayListType parecería la list y length tienen que ser algún tipo de variables globales.)

Tendrá que decirle al compilador explícitamente que los nombres son de hecho, depende de la instanciación del padre.

De una forma, usando this-> antes de todos los nombres heredados: this->list, this->length.

Otra forma, usando declaraciones: using arrayListType<elemType>::length; etc. (por ejemplo, en la sección privada de la clase derivada).


Una entrada de la FAQ sobre esto: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.19

+0

¡Gracias! Usé "using arrayListType :: length" y eso resolvió los errores relacionados con las variables que no se declararon en el alcance. Solo tengo un error más que publiqué al final de la pregunta. Podrías por favor comentar sobre eso. ¡Gracias! – Romonov

+2

@ user640639: El último mensaje de error parece arruinado, pero lo que le está diciendo es que no ha definido una función miembro que haya declarado. Las funciones de los miembros virtuales deben definirse independientemente de si se utilizan en su código o no, y usted no ha proporcionado la implementación de ese en particular. –

+0

@Rodriguez ¡Gracias! Tienes razón. Hubo un error en la declaración de función virtual de seqSearch. Lo corregí y funciona ahora. – Romonov

5

me gustaría probar dos cosas:

1. Uso this-> (que generalmente es una buena idea hacer con plantillas).

template <class elemType> 
void unorderedArrayListType<elemType>::insertAt(int location, const elemType& insertItem) 
{ 
    for(int i = this->length; i > location; i--) 
     this->list[i] = this->list[i - 1]; 

    this->list[location] = insertItem; 
    this->length++; 
} 

2. Typedef los padres y usarla cuando se accede a los padres miembros:

template <class elemType> 
class unorderedArrayListType: public arrayListType<elemType> 
{ 
    typedef arrayListType<elemType> Parent; 
    ... 
} 

template <class elemType> 
void unorderedArrayListType<elemType>::insertAt(int location, const elemType& insertItem) 
{ 
    for(int i = Parent::length; i > location; i--) 
     Parent::list[i] = Parent::list[i - 1]; 

    Parent::list[location] = insertItem; 
    Parent::length++; 
} 
9

Un comentario adicional en respuesta UncleBens'.

Siempre es bueno tener en cuenta que las plantillas de clase no son clases. Son plantillas. Una forma de verlo: en C++, las clases no son objetos. Necesita crear una instancia de una clase para crear un objeto. Un concepto similar se aplica a las plantillas y clases de clase. Así como la creación de instancias de clases crea un objeto, la creación de instancias de plantillas crea una clase.

Hasta que se crea una instancia de la plantilla, esa relación de herencia que configura entre unorderedArrayListType y arrayListType no existe del todo. El compilador no sabe si va a definir una instancia de plantilla parcial de arrayListType que no tiene length y list como miembros de datos. Necesitas darle una mano al compilador en tu unorderedArrayListType usando this->length y this->list o alguna otra construcción que le diga al compilador que esperas que estos sean miembros de los datos.

supongamos que utiliza this->length en unorderedArrayListType, y supongamos que alguien viene y escribe una de instancias de plantilla parcial de arrayListType<FooType> que no tiene length y list como miembros de datos. Ahora instanciar un unorderedArrayListType<FooType> dará como resultado un error de tiempo de compilación. Pero dado que no vas a hacer eso (no vas a hacer eso, ¿o sí?), Usar this->length estará bien.

+1

¿Cómo escribiría una "instanciación de plantilla parcial de arrayListType que no tiene longitud y lista como miembros de datos "? ¿Podría agregar un ejemplo a su respuesta? Gracias. –

Cuestiones relacionadas