J'ai les 4 fichiers suivants:
arrayListType.h
: Déclarez et définissez arrayListType
classe en tant que modèleunorderedArrayListType.h
: Hérité de arrayListType
classe et déclare et définit unorderedArrayListType
comme modèle.main1.cpp
: Programme de test pour tester unorderedArrayListType
classe.Makefile
Je reçois une erreur de compilation disant lors de l'accès aux variables protégées de arrayListType
in unorderedArrayListType
par exemple: "La longueur non déclarée dans la présente étendue", "liste non déclarée dans cette portée", où la longueur et la liste sont des variables protégées dans arrayListType
classe.
Voici les codes suivants:
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
oNUERDARRAYLISTTYPE.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
Voici l'erreur de compilation:
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
Plus de fonctions de unorderedArrayListType
variables répertoriées et protégées indiquées comme non déclarées dans la portée. Se demandant ce qui pourrait être l'erreur.
Nouvelle erreur:
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'
En effet, le parent modèle d'une classe de modèle n'est pas instancié au cours de la passe de compilation qui examine d'abord le modèle. Ces noms semblent être non dépendants de l'instanciation de gabarits particulière et, par conséquent, les définitions doivent être disponibles. (Si vous ne regardez jamais la définition de arrayListType
, puis lisez le code de unorderedArrayListType
_ Cela apparaîtrait le list
et length
doit être une sorte de Globals.)
Vous devrez dire explicitement au compilateur que les noms dépendent en fait de l'instanciation du parent.
Une façon, en utilisant this->
Avant tous les noms hérités: this->list
, this->length
.
Autre moyen, en utilisant des déclarations: using arrayListType<elemType>::length;
c (par exemple dans la section privée de la classe dérivée).
A FAQ Entrée sur ceci: https://isocpp.org/wiki/faq/templates#nondépendant-name-lookup-members
Un commentaire étendu sur la réponse des Onclebens.
Il est toujours bon de garder à l'esprit que les modèles de classe ne sont pas des cours. Ce sont des modèles. Une façon de l'examiner: en C++, les classes ne sont pas des objets. Vous devez instancier une classe pour créer un objet. Un concept similaire s'applique aux modèles de classe et aux classes. Tout comme l'instanciation de classe crée un objet, l'instanciation de modèle de classe crée une classe.
Jusqu'à ce que le modèle soit instancié, cette relation de héritage que vous avez configurée entre unorderedArrayListType
et arrayListType
n'existe pas tout à fait. Le compilateur ne sait pas si vous allez définir une instanciation de modèle partielle de arrayListType
qui n'a pas length
et list
comme membres de données. Vous devez donner au compilateur une main dans votre unorderedArrayListType
en utilisant this->length
et this->list
ou une autre construction qui indique au compilateur que vous vous attendez à ce que ce soit des membres de données.
Supposons que vous utilisiez this->length
dans unorderedArrayListType
et supposons que quelqu'un vienne et écrit une instanciation de gabarits partiels de arrayListType<FooType>
Cela n'a pas length
et list
comme membres de données. Maintenant instanciant d'un unorderedArrayListType<FooType>
entraînera une erreur de compilation. Mais puisque tu ne vas pas faire ça (tu n'allais pas faire ça, es-tu?), En utilisant this->length
sera OK.
J'essaierais deux choses:
1. Utilisez this->
(qui est généralement une bonne idée de faire avec des modèles).
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 le parent et utilisez-le lors de l'accès aux membres des parents :
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++;
}