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

Rom*_*nov 37 c++ inheritance templates makefile class

我有以下4个文件:

  1. arrayListType.h:声明并定义arrayListType类作为模板
  2. unorderedArrayListType.h:继承自arrayListTypeclass和Declares并定义unorderedArrayListType为模板.
  3. main1.cpp:测试程序测试unorderedArrayListType类.
  4. Makefile

我得到一个编译错误的访问受保护的变量时说,arrayListTypeunorderedArrayListType举例说:"在此范围内未声明的长度",其中长度和列表在保护变量"在此范围内不宣布名单" 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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

以下是编译错误:

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  
Run Code Online (Sandbox Code Playgroud)

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'  
Run Code Online (Sandbox Code Playgroud)

Unc*_*ens 66

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

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

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

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


关于此的FAQ条目:http://www.parashift.com/c++-faq-lite/templates.html#faq-35.19

  • @ user640639:最后一条错误消息看起来很糟糕,但它告诉你的是你还没有定义你声明的成员函数.必须定义虚拟成员函数是否在代码中使用它们,并且您没有提供该特定函数的实现. (2认同)

Dav*_*men 12

对UncleBens答案的延伸评论.

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

直到模板实例,是继承关系,你之间建立unorderedArrayListTypearrayListType完全不是那么回事存在.编译器不知道,如果你要定义的部分模板实例arrayListType不具有lengthlist数据成员.您需要unorderedArrayListType通过使用this->length和/ this->list或一些其他构造向编译器提供帮助,告诉编译器您确实希望这些构造成为数据成员.

假设你使用this->lengthunorderedArrayListType,并假设有人走来,并写入的部分模板实例arrayListType<FooType>不具有lengthlist数据成员.现在实例化unorderedArrayListType<FooType>将导致编译时错误.但既然你不打算这样做(你不打算这样做,不是吗?),使用this->length就行了.


sel*_*rer 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++;
}
Run Code Online (Sandbox Code Playgroud)

2.键入dede父级并在访问父级成员时使用它:

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++;
}
Run Code Online (Sandbox Code Playgroud)