テンプレート:継承されたクラスに表示されない親クラスのメンバー変数

c++ class inheritance makefile templates
テンプレート:継承されたクラスに表示されない親クラスのメンバー変数

次の4つのファイルがあります。

  1. arrayListType.h:` arrayListType`クラスを宣言し、定義します
    テンプレート

  2. unorderedArrayListType.h:` arrayListType`クラスから継承し、
    `unorderedArrayListType`をテンプレートとして宣言および定義します。

  3. main1.cpp:` unorderedArrayListType`クラスをテストするテストプログラム。

  4. Makefile

unorderedArrayListType`の arrayListType`の保護変数にアクセスすると、コンパイルエラーが発生します。たとえば、「長さはこのスコープで宣言されていません」、「リストはこのスコープで宣言されていません」、長さとリストは `arrayListTypeの保護変数です`クラス。

コードは次のとおりです。+ arrayListType.h

#ifndef H_arrayListType
#define H_arrayListType

#include

using namespace std;

template
class arrayListType
{

public:

    const arrayListType&operator=(const arrayListType&);

    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& otherList);

    virtual ~arrayListType();


protected:

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


template
bool arrayListType::isEmpty() const
{
    return (length == 0);
}

// remaining non-virtual functions of arrayListType class

#endif

unorderedArrayListType.h

#ifndef H_unorderedArrayListType
#define H_unorderedArrayListType

//#include
#include "arrayListType.h"

//using namespace std;

template
class unorderedArrayListType: public arrayListType
{

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
void unorderedArrayListType::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
#include "unorderedArrayListType.h"

using namespace std;


int main()
{
    unorderedArrayListType 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<

メークファイル:

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

  31  11


ベストアンサー

これは、テンプレートを最初に検査するコンパイルパス中に、テンプレートクラスのテンプレート親がインスタンス化されないためです。 これらの名前は、特定のテンプレートのインスタンス化に依存していないように見えるため、定義が利用可能である必要があります。 ( arrayListType`の定義を見たことがない場合、 unorderedArrayListType`のコードを読み取ると、 list`と length`が何らかのグローバルである必要があります。)

名前は実際には親のインスタンス化に依存していることをコンパイラーに明示的に伝える必要があります。

1つの方法は、継承されたすべての名前の前に this→`を使用することです: `this→ list、` this→ length`。

別の方法として、宣言を使用します: `using arrayListType

length;`など(派生クラスのprivateセクションなど)。

” ” ‘

これに関するFAQエントリ:http://www.parashift.com/c++-faq-lite/templates.html#faq-35.19

58


UncleBensの回答に対する拡張コメント。

クラステンプレートはクラスではないことに注意してください。 それらはテンプレートです。 一見すると、C ++では、クラスはオブジェクトではありません。 オブジェクトを作成するには、クラスをインスタンス化する必要があります。 同様の概念がクラステンプレートとクラスに適用されます。 クラスのインスタンス化がオブジェクトを作成するように、クラステンプレートのインスタンス化はクラスを作成します。

テンプレートがインスタンス化されるまで、 unorderedArrayListType`と arrayListType`の間に設定した継承関係はまったく存在しません。 コンパイラは、データメンバとして「長さ」と「リスト」を持たない「arrayListType」の部分的なテンプレートインスタンスを定義するかどうかを知りません。 this→ length`と this→ list`を使用するか、コンパイラにこれらがデータメンバーであると期待することを伝える他の構造を使用して、コンパイラに `unorderedArrayListType`を渡す必要があります。

unorderedArrayListType`で this→ length`を使用し、データメンバーとして length`と list`を持たない `arrayListType`の部分的なテンプレートインスタンス化を誰かが書いたと仮定します。 「unorderedArrayListType」をインスタンス化すると、コンパイル時エラーが発生します。 しかし、あなたはそうするつもりはないので(そうするつもりはないのですか?)、 `this→ length`を使用することは問題ありません。

11


私は二つのことを試みるでしょう:

1. `this→`を使用します(通常、テンプレートを使用することをお勧めします)。

template
void unorderedArrayListType::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 unorderedArrayListType: public arrayListType
{
    typedef arrayListType Parent;
    ...
}

template
void unorderedArrayListType::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++;
}

5


タイトルとURLをコピーしました