2011-07-06 96 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 没有长度和列表作为数据成员“?你能给你的答案增加一个例子吗?谢谢。 –