resueltos poo herencia ejercicios ejemplos derivada codigo clases clase c++ class templates inheritance makefile

c++ - poo - herencia de clases



plantillas: variables de miembro de clase principal no visibles en clase heredada (3)

Esto se debe a que el elemento primario de la plantilla de una clase de plantilla no se crea una instancia durante el paso de compilación que primero examina 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 la definición de arrayListType , entonces leyendo el código de unorderedArrayListType parecería que la list y la length deben ser un tipo de globales).

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

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 preguntas frecuentes sobre esto: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.19

Tengo los siguientes 4 archivos:

  1. arrayListType.h : arrayListType.h y defina clase arrayListType como plantilla
  2. arrayListType : Heredado de la clase arrayListType y Declara y define unorderedArrayListType como una plantilla.
  3. main1.cpp : Programa de prueba para probar la clase main1.cpp unorderedArrayListType .
  4. Makefile

arrayListType un error de compilación al acceder a las variables protegidas de arrayListType en arrayListType por ejemplo: "longitud no declarada en este ámbito", "lista no declarada en este ámbito", donde longitud y lista son variables protegidas en 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 enumeradas y variables protegidas indicadas como no declaradas en el alcance. Preguntándose cuál podría ser el error.

Nuevo 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''


Intentaría dos cosas:

1. Use 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. Escribadef el padre y úselo cuando acceda a los miembros padres:

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


Un comentario extendido sobre la respuesta de 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 cree una instancia de la plantilla, la relación de herencia que establezca entre arrayListType y arrayListType no existe del todo. El compilador no sabe si va a definir una instanciación 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 sean miembros de los datos.

Supongamos que utiliza this->length en unorderedArrayListType , y supongamos que alguien aparece y escribe una instancia de plantilla parcial de arrayListType<FooType> que no tiene length y list como miembros de datos. Ahora crear instancias de 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, ¿verdad?), this->length estará bien.