次の4つのファイルがあります。
arrayListType.h
:arrayListType
クラスをテンプレートとして宣言および定義しますunorderedArrayListType.h
:arrayListType
クラスから継承され、unorderedArrayListType
をテンプレートとして宣言および定義します。main1.cpp
:unorderedArrayListType
クラスをテストするテストプログラム。Makefile
arrayListType
内のunorderedArrayListType
の保護された変数にアクセスすると、コンパイルエラーが発生します。たとえば、「このスコープでは宣言されていない長さ」、「このスコープでは宣言されていないリスト」、ここで長さとリスト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'
これは、テンプレートクラスのテンプレートの親が、最初にテンプレートを検査するコンパイルパス中にインスタンス化されないためです。これらの名前は特定のテンプレートのインスタンス化に依存していないように見えるため、定義を使用できるようにする必要があります。 (arrayListType
の定義を決して見ない場合、unorderedArrayListType
のコードを読み取ると、list
とlength
は、グローバル。)
名前は実際には親のインスタンス化に依存していることをコンパイラに明示的に通知する必要があります。
this->
すべての継承名の前:this->list
、this->length
。
宣言を使用する別の方法:using arrayListType<elemType>::length;
など(派生クラスのプライベートセクションなど)。
A FAQこのエントリ: https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-members
UncleBensの回答に関する拡張コメント。
クラステンプレートはクラスではないことに注意してください。それらはテンプレートです。 C++では、クラスはオブジェクトではありません。オブジェクトを作成するには、クラスをインスタンス化する必要があります。同様の概念がクラステンプレートとクラスに適用されます。クラスのインスタンス化によってオブジェクトが作成されるのと同じように、クラステンプレートのインスタンス化によってクラスが作成されます。
テンプレートがインスタンス化されるまで、unorderedArrayListType
とarrayListType
の間に設定した継承関係は完全には存在しません。コンパイラーは、arrayListType
とlength
をデータメンバーとして持たないlist
の部分的なテンプレートのインスタンス化を定義するかどうかを認識しません。 _this->length
_および_this->list
_、またはこれらをデータメンバーであると予期していることをコンパイラーに通知するその他の構成要素を使用して、unorderedArrayListType
でコンパイラーに手を与える必要があります。
unorderedArrayListType
で_this->length
_を使用し、誰かがやって来て、length
とlist
をデータメンバーとして持たない_arrayListType<FooType>
_の部分的なテンプレートのインスタンス化を書いたとします。 _unorderedArrayListType<FooType>
_をインスタンス化すると、コンパイル時エラーが発生します。しかし、そうするつもりはないので(そうするつもりはないのですか?)、_this->length
_を使用しても問題ありません。
私は2つのことを試みます:
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。親をTypedefし、親メンバーにアクセスするときに使用します:
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++;
}