我有以下4个文件:
arrayListType.h
:声明并定义arrayListType
类作为模板unorderedArrayListType.h
:从arrayListType
类继承并声明并定义unorderedArrayListType
作为模板。 main1.cpp
:测试程序以测试unorderedArrayListType
类。 Makefile
我在访问arrayListType
中unorderedArrayListType
的受保护变量时遇到编译错误,例如:“未在此范围内声明的长度”,“未在此范围内声明的列表”,其中长度和list是arrayListType
类中的受保护变量。
以下是代码:
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
以下是编译错误:
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
unorderedArrayListType
列出的和受保护变量的更多函数表示未在范围中声明。想知道可能是什么错误。
新错误:
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'
答案 0 :(得分:63)
这是因为模板类的模板父级在首次检查模板的编译过程中未实例化。这些名称似乎不依赖于特定的模板实例化,因此需要提供定义。 (如果你从不查看arrayListType
的定义,那么阅读unorderedArrayListType
的代码就会显示list
和length
需要某种全局变量。)< / p>
您需要明确告诉编译器这些名称实际上取决于父级的实例化。
一种方法是,在所有继承的名称之前使用this->
:this->list
,this->length
。
另一种方法,使用声明:using arrayListType<elemType>::length;
等(例如在派生类的私有部分中)。
关于此问题的常见问题解答:https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-members
答案 1 :(得分:11)
对UncleBens答案的延伸评论。
总是很好的是要记住,类模板不是类。它们是模板。一种看待它的方法:在C ++中,类不是对象。您需要实例化一个类来创建一个对象。类似的概念适用于类模板和类。就像类实例化创建一个对象一样,类模板实例化也会创建一个类。
在实例化模板之前,您在unorderedArrayListType
和arrayListType
之间设置的继承关系并不存在。编译器不知道您是否要将arrayListType
的部分模板实例化定义为没有length
和list
作为数据成员。您需要使用unorderedArrayListType
和this->length
或其他一些构造告诉编译器您希望这些构造成为数据成员,从而为编译器提供this->list
。
假设您在this->length
中使用unorderedArrayListType
,并假设某人出现并编写了arrayListType<FooType>
的部分模板实例,该实例没有length
和{{1}作为数据成员。现在实例化list
将导致编译时错误。但既然你不打算这样做(你不打算这样做,不是吗?),使用unorderedArrayListType<FooType>
就行了。
答案 2 :(得分:6)
我会尝试两件事:
<强> 1。使用this->
(这通常是模板的好主意。)
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。键入dede the parent并在访问父成员时使用它:
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++;
}