2011-07-06 99 views
23

我有以下4個文件不可見:模板:父類的成員變量在繼承類

  1. arrayListType.h:聲明並定義arrayListType類爲模板
  2. unorderedArrayListType.h:從arrayListType類繼承,並聲明和定義unorderedArrayListType作爲模板。測試程序類。
  3. 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; 
} 

生成文件:

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 

以下是編譯錯誤:unorderedArrayListType指示爲範圍沒有宣佈上市和受保護的變量的

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 

更多的功能。想知道可能是什麼錯誤。

新的錯誤:

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' 
+1

可能的重複[爲什麼我必須通過此指針訪問模板基類成員?](http://stackoverflow.com/questions/4643074/why-do-i-have-to-access-template-基地級會員通過這個指針) – Pradhan

回答

47

這是因爲模板類的模板父編譯通首先檢查模板期間不實例化。這些名稱似乎不依賴於特定的模板實例化,因此定義需要可用。 (如果你從來不看的arrayListType定義,然後閱讀unorderedArrayListType的代碼將出現在listlength需要是某種全局的。)

你需要明確地告訴編譯器,這個名稱是實際上取決於父母的實例化。

單程,在所有繼承名稱前使用this->this->listthis->length

另一種方式,使用聲明:using arrayListType<elemType>::length;等(例如在派生類的私人部分)。


基於此的一個FAQ條目:http://www.parashift.com/c++-faq-lite/templates.html#faq-35.19

+0

謝謝!我使用「使用arrayListType :: length」,並解決了與未在範圍中聲明的變量有關的錯誤。我只是在問題結尾處發佈了另外一個錯誤。你能否就此評論一下。謝謝! – Romonov

+2

@ user640639:最後一條錯誤消息看起來很亂,但它告訴你的是你還沒有定義你聲明的成員函數。必須定義虛擬成員函數是否在你的代碼中使用,並且你沒有提供那個特定的實現。 –

+0

@Rodriguez謝謝!你是對的。我的seqSearch的虛函數聲明有錯誤。我糾正了這一點,它現在起作用了。 – Romonov

5

我將要做兩件事情:

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

上UncleBens'回答的擴展評論。

記住類模板不是類是很好的。他們是模板。一種看待它的方法:在C++中,類不是對象。你需要實例化一個類來創建一個對象。一個類似的概念適用於類模板和類。就像類實例化創建對象一樣,類模板實例化也會創建一個類。

在實例化模板之前,您在unorderedArrayListTypearrayListType之間設置的繼承關係並不完全存在。編譯器不知道是否要定義arrayListType的部分模板實例,該實例不具有lengthlist作爲數據成員。您需要通過使用this->lengththis->list或其他一些結構告訴編譯器,您確實希望這些數據成員是數據成員,從而使編譯器能夠在unorderedArrayListType中掌握。

假設你在unorderedArrayListType使用this->length,並假設有人走來,並寫入的arrayListType<FooType>部分模板實例不具有lengthlist作爲數據成員。現在實例化一個unorderedArrayListType<FooType>將導致編譯時錯誤。但既然你不打算這樣做(你不打算這樣做,是嗎?),使用this->length將是確定的。

+1

你會怎麼寫一個「部分模板實例的arrayListType 沒有長度和列表作爲數據成員「?你能給你的答案增加一個例子嗎?謝謝。 –