【问题标题】:Compiler error in declaring template friend class within a template class在模板类中声明模板友元类时出现编译器错误
【发布时间】:2010-12-31 21:32:46
【问题描述】:

出于教学目的,我一直在尝试实现自己的链表类。

我在迭代器声明中将“List”类指定为友元,但它似乎无法编译。

这些是我使用过的 3 个类的接口:

Node.h:

#define null (Node<T> *) 0

template <class T>
class Node {
 public:
    T content;
    Node<T>* next;
    Node<T>* prev;

    Node (const T& _content) :
        content(_content),
        next(null),
        prev(null)
    {}
};

Iterator.h:

#include "Node.h"

template <class T>
class Iterator {
 private:
    Node<T>* current;

    Iterator (Node<T> *);

 public:
    bool isDone () const;

    bool hasNext () const;
    bool hasPrevious () const;
    void stepForward ();
    void stepBackwards ();

    T& currentElement () const;

    friend class List<T>;
};

List.h

#include <stdexcept>
#include "Iterator.h"

template <class T>
class List {
 private:
    Node<T>* head;
    Node<T>* tail;
    unsigned int items;

 public:
    List ();

    List (const List<T>&);
    List& operator = (const List<T>&);

    ~List ();

    bool isEmpty () const {
        return items == 0;
    }
    unsigned int length () const {
        return items;
    } 
    void clear ();

    void add (const T&);
    T remove (const T&) throw (std::length_error&, std::invalid_argument&);

    Iterator<T> createStartIterator () const throw (std::length_error&);
    Iterator<T> createEndIterator () const throw (std::length_error&);
};

这是我一直试图运行的测试程序:

trial.cpp

using namespace std;
#include <iostream>
#include "List/List.cc"

int main ()
{
 List<int> myList;

 for (int i = 1; i <= 10; i++) {
  myList.add(i);
 }

 for (Iterator<int> it = myList.createStartIterator(); !it.isDone(); it.stepForward()) {
  cout << it.currentElement() << endl;
 }

 return 0;
}

当我尝试编译它时,编译器给了我以下错误:

Iterator.h:26:错误:“列表”不是模板

Iterator.h:在“Iterator”的实例化中:

trial.cpp:18:从这里实例化

Iterator.h:12:错误:“结构列表”需要模板参数

List.cc:在成员函数'Iterator List::createStartIterator() const [with T = int]'中:

trial.cpp:18:从这里实例化

Iterator.h:14: 错误:'Iterator::Iterator(Node*) [with T = int]' 是私有的

List.cc:120:错误:在此上下文中

似乎它无法识别朋友声明。 我哪里做错了?

【问题讨论】:

  • 不要定义自己的 null(或 NULL,或任何相关的)宏。在初始化数据成员的情况下,0 工作得很好。
  • 我知道这很丑,只是暂时的。但我很确定 C++ 不允许隐式转换。
  • 强制转换永远不会是隐式的,但转换是。 (您可能会说,同一硬币的两面,“转换”也用于命名在其他用途​​中转换值的方法,但这是一种不同类型的转换。)您需要初始化一个指针是另一个指针合适的类型,或空指针常量; 0 是一个非常好的空指针常量(NULL 也是,如果你愿意的话)。
  • 在一般情况下,您还需要在标头中定义类模板的 (List's) 方法(而不是 List.cc,它不应该在好的代码中#included),因为类模板和函数模板并不是真正的类和函数,它们生成类和函数,并且编译器必须可以使用完整的代码。

标签: c++ templates compiler-errors friend


【解决方案1】:

问题是 List 没有在 Iterator.h 中正确声明。相反,将 Iterator 类嵌套在 List 中(自动使其成为模板),无论如何您都可能想要这样做(使用 List::Iterator 而不是将其重命名为 ListIterator 或 IteratorForList,因为您将拥有多个 Iterator在命名空间中)。

template<class T>
struct List {
  //...
  struct Node {/*...*/};
  struct Iterator {
    // ...
  private:
    Iterator(Node*);
    friend class List; // still required
  };
  //...
};

【讨论】:

    【解决方案2】:

    尝试添加前向声明

    template <class T> class List;
    

    Iterator.h 的开头——这可能是您允许Iterator 类中的friend 声明工作所需要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-18
      • 1970-01-01
      • 1970-01-01
      • 2017-02-09
      • 1970-01-01
      • 2011-10-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多