【问题标题】:templates: parent class member variables not visible in inherited class模板:父类成员变量在继承类中不可见
【发布时间】:2011-09-29 08:50:19
【问题描述】:

我有以下 4 个文件:

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

当访问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

以下是编译错误:

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'  

【问题讨论】:

标签: c++ class templates inheritance makefile


【解决方案1】:

这是因为模板类的模板父级在首先检查模板的编译过程中没有实例化。这些名称似乎不依赖于特定的模板实例化,因此这些定义需要可用。 (如果您从不查看arrayListType 的定义,那么阅读unorderedArrayListType 的代码会发现listlength 需要是某种全局变量。)

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

一种方法,在所有继承名称之前使用this-&gt;this-&gt;listthis-&gt;length

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


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

【讨论】:

  • 谢谢!我使用了“使用 arrayListType::length”并解决了与未在范围内声明的变量相关的错误。我只是在问题结束时发布了另一个错误。你能否对此发表评论。谢谢!
  • @user640639:最后一条错误消息看起来很混乱,但它告诉您的是您尚未定义已声明的成员函数。无论是否在您的代码中使用虚成员函数,都必须定义它们,并且您还没有提供该特定函数的实现。
  • @Rodriguez 谢谢!你说的对。我的 seqSearch 的虚函数声明中有错误。我纠正了这一点,它现在可以工作了。
【解决方案2】:

对 UncleBens 回答的扩展评论。

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

在模板被实例化之前,您在unorderedArrayListTypearrayListType 之间建立的继承关系并不完全存在。编译器不知道您是否要定义不具有lengthlist 作为数据成员的arrayListType 的部分模板实例化。您需要通过使用this-&gt;lengththis-&gt;list 或其他一些告诉编译器您确实希望它们是数据成员的构造来帮助编译器处理您的unorderedArrayListType

假设您在unorderedArrayListType 中使用this-&gt;length,并假设有人出现并编写了arrayListType&lt;FooType&gt; 的部分模板实例化,它没有lengthlist 作为数据成员。现在实例化unorderedArrayListType&lt;FooType&gt; 将导致编译时错误。但既然你不会那样做(你不会那样做,是吗?),使用this-&gt;length 就可以了。

【讨论】:

  • 您将如何编写“没有长度和列表作为数据成员的 arrayListType 的部分模板实例化”?您可以在答案中添加一个示例吗?谢谢。
【解决方案3】:

我会尝试两件事:

1.使用this-&gt;(这通常是使用模板的好主意)。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-03
    • 2018-11-15
    • 2018-12-03
    • 1970-01-01
    • 2012-03-13
    • 2010-12-06
    • 2016-12-03
    • 1970-01-01
    相关资源
    最近更新 更多