templates:父类成员变量在继承的类中不可见

时间:2011-07-06 06:44:34

标签: c++ class templates inheritance makefile

我有以下4个文件:

  1. arrayListType.h:声明并定义arrayListType类作为模板
  2. unorderedArrayListType.h:从arrayListType类继承并声明并定义unorderedArrayListType作为模板。
  3. main1.cpp:测试程序以测试unorderedArrayListType类。
  4. Makefile
  5. 我在访问arrayListTypeunorderedArrayListType的受保护变量时遇到编译错误,例如:“未在此范围内声明的长度”,“未在此范围内声明的列表”,其中长度和list是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'  
    

3 个答案:

答案 0 :(得分:63)

这是因为模板类的模板父级在首次检查模板的编译过程中未实例化。这些名称似乎不依赖于特定的模板实例化,因此需要提供定义。 (如果你从不查看arrayListType的定义,那么阅读unorderedArrayListType的代码就会显示listlength需要某种全局变量。)< / p>

您需要明确告诉编译器这些名称实际上取决于父级的实例化。

一种方法是,在所有继承的名称之前使用this->this->listthis->length

另一种方法,使用声明:using arrayListType<elemType>::length;等(例如在派生类的私有部分中)。


关于此问题的常见问题解答:https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-members

答案 1 :(得分:11)

对UncleBens答案的延伸评论。

总是很好的是要记住,类模板不是类。它们是模板。一种看待它的方法:在C ++中,类不是对象。您需要实例化一个类来创建一个对象。类似的概念适用于类模板和类。就像类实例化创建一个对象一样,类模板实例化也会创建一个类。

在实例化模板之前,您在unorderedArrayListTypearrayListType之间设置的继承关系并不存在。编译器不知道您是否要将arrayListType的部分模板实例化定义为没有lengthlist作为数据成员。您需要使用unorderedArrayListTypethis->length或其他一些构造告诉编译器您希望这些构造成为数据成员,从而为编译器提供this->list

假设您在this->length中使用unorderedArrayListType,并假设某人出现并编写了arrayListType<FooType>的部分模板实例,该实例没有length和{{1}作为数据成员。现在实例化list将导致编译时错误。但既然你不打算这样做(你不打算这样做,不是吗?),使用unorderedArrayListType<FooType>就行了。

答案 2 :(得分:6)

我会尝试两件事:

<强> 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。键入dede the parent并在访问父成员时使用它:

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