2011-07-06 10 views
23

mam 4 poniższe pliki:szablony: zmienne składowe klasy rodzic nie widocznych w dziedziczonej klasie

  1. arrayListType.h: zadeklarować i definiują arrayListType klasę jako szablon
  2. unorderedArrayListType.h: odziedziczona arrayListType klasy i deklaruje i tworzy unorderedArrayListType jako szablon.
  3. main1.cpp: Testuj program, aby przetestować klasę unorderedArrayListType.
  4. Makefile

otrzymuję błąd kompilacji mówiąc podczas uzyskiwania dostępu do chronionych zmiennych arrayListType w unorderedArrayListType na przykład: „długość nie zadeklarowane w tym zakresie”, „lista nie zadeklarowane w tym zakresie”, gdzie długość i listy są chronionymi zmiennymi w klasie arrayListType.

są następujące odnośniki:
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 

Poniżej znajduje się błąd kompilacji:

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 

Więcej funkcje unorderedArrayListType giełdowych i chronionych zmiennych wskazanych jako nie zadeklarowane w tym zakresie. Zastanawiasz się, jaki może być błąd.

New błąd:

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

prawdopodobny duplikat [Dlaczego muszę uzyskać dostęp do podstawowych elementów szablonu za pomocą tego wskaźnika?] (Http://stackoverflow.com/questions/4643074/why-do-i-have-to-access-template- członkowie-klasy-po-tym-wskaźniku) – Pradhan

Odpowiedz

47

To dlatego, że szablon nadrzędny klasy szablonu nie jest tworzony podczas kompilacji przełęczy że najpierw bada szablonu. Nazwy te wydają się być niezależne od konkretnej instancji szablonu, dlatego też definicje muszą być dostępne. (Jeżeli nie spojrzeć na definicję arrayListType, a następnie odczytanie kodu unorderedArrayListType byłoby pojawić list i length musi być jakiś globalnych.)

Musisz poinformować kompilator wyraźnie, że nazwy są w rzeczywistości zależy to od postawienia rodzica.

W jedną stronę, używając wszystkich nazw odziedziczonych: this->list, this->length.

Inny sposób, używając deklaracji: using arrayListType<elemType>::length; itd. (Na przykład w prywatnej sekcji klasy pochodnej).


Wpis FAQ na ten temat: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.19

+0

Dzięki! Użyłem "using arrayListType :: length" i to rozwiązało błędy związane ze zmiennymi, które nie są zadeklarowane w zakresie. Mam jeszcze jeden błąd, który opublikowałem pod koniec pytania. Czy mógłbyś to skomentować? Dzięki! – Romonov

+2

@ user640639: Ostatni komunikat o błędzie wygląda na zniekształcony, ale to, co mówi, to to, że nie zdefiniowałeś funkcji członka, którą zadeklarowałeś. Funkcje wirtualnego użytkownika muszą być zdefiniowane, czy są używane w kodzie, czy nie, i nie dostarczyłeś implementacji tego konkretnego. –

+0

@Rodriguez Dzięki! Masz rację. Wystąpił błąd w deklaracji funkcji wirtualnej seqSearch. Poprawiłem to i teraz działa. – Romonov

5

chciałbym spróbować dwóch rzeczy:

1. Korzystając this-> (co jest generalnie dobry pomysł, aby zrobić z szablonów).

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 rodzica i używać go podczas dostępu członków nadrzędny:

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

Rozszerzony komentarz na odpowiedź UncleBens.

Zawsze dobrze jest pamiętać, że szablony klas nie są klasami. Są szablonami. Jeden sposób na to: W C++ klasy nie są obiektami. Musisz utworzyć instancję klasy, aby utworzyć obiekt. Podobna koncepcja dotyczy szablonów klas i klas. Tak jak instancja klasy tworzy obiekt, tworzenie instancji klasy tworzy klasę.

Do momentu utworzenia instancji, ta relacja dziedziczenia ustawiona między unorderedArrayListType i arrayListType nie istnieje. Kompilator nie wie, czy zamierzasz zdefiniować częściową instancję szablonu o numerze arrayListType, która nie ma length ani list jako elementów danych. Musisz podać kompilatorowi swój numer unorderedArrayListType, używając this->length i this->list lub innej konstrukcji, która mówi kompilatorowi, że spodziewasz się, że będą to elementy danych.

Załóżmy użyć this->length w unorderedArrayListType, i załóżmy, że ktoś przyjdzie i pisze częściową szablonu konkretyzacji arrayListType<FooType> że nie ma length i list jako członkowie danych. Utworzenie instancji unorderedArrayListType<FooType> spowoduje błąd kompilacji. Ale ponieważ nie zamierzasz tego zrobić (nie zamierzasz tego zrobić, prawda?), Użycie this->length będzie OK.

+1

Jak napisać "częściową instancję szablonu tablicyListType , która nie ma długość i lista jako członków danych "? Czy możesz dodać przykład do swojej odpowiedzi? Dzięki. –

Powiązane problemy