【问题标题】:ostream << operator with template class, cannot access private membersostream << 带有模板类的运算符,不能访问私有成员
【发布时间】:2014-12-20 19:18:53
【问题描述】:

我按照我在stackoverflow上找到的说明来实现链表模板类,我做了如下:

template<typename T> class List;
template<typename T> std::ostream& operator<<(std::ostream&, const List<T>&);

template<typename T>
class List {
private:
    struct Item {
        T value;
        Item *next;
        Item *prev;

        Item(const T &value, Item *next, Item *prev)
                : value(value), next(next), prev(prev) {
        }
    };

    Item *head;
    Item *tail;
    int size;
public:
    List();    
    ~List();    
    List(const List&) = delete;    
    List& operator=(const List &) = delete;    
    friend std::ostream& operator<< <>(std::ostream&, const List<T>&);
};

template <typename T>
std::ostream& operator<<(std::ostream& os, const List<T>& list) {
    Item* p = list.head;
    while (p != NULL) {
        os << p->value << " ";
        p = p->next;
    }
    return os;
}

但是我得到一个错误

error: 'Item' was not declared in this scope

我不知道它是如何加好友的,所以我应该可以访问所有私人成员,对吧?

【问题讨论】:

  • 友元声明 'std::ostream& operator&)' 声明一个非模板函数
  • 是的,没关系:-S
  • 列表类型要么是typename List&lt;T&gt;::Item,要么你可以说:for (auto p = list.head; p; p = p-&gt;next) { os &lt;&lt; p-&gt;value &lt;&lt; " "; }

标签: c++ templates private friend


【解决方案1】:

ItemList 的每个类模板特化的成员,无法在 全局函数(模板)operator&lt;&lt; 中找到。您需要typename List&lt;T&gt;::Item 才能在List&lt;T&gt; 类中查找名称Item

template <typename T>
std::ostream& operator<<(std::ostream& os, const List<T>& list) {
    typename List<T>::Item* p = list.head; // <- here
    while (p != NULL) {
        os << p->value << " ";
        p = p->next;
    }
    return os;
}

【讨论】:

  • 我不确定这是否是你的意思,但我将它添加到这样的实现中 List::Item* p = list.head;这给出了错误“'p'没有在这个范围内声明”
  • 嗯。我不完全明白你做了什么。请参阅我的答案中最近添加的代码块和这个实时示例:coliru.stacked-crooked.com/a/f4722d370aaefa97(我为构造函数和析构函数添加了虚拟实现)
  • 谢谢你,这很有效,但是我不知道如何以及为什么,我从来没有在这种情况下见过 typename 关键字
  • Where and why do I have to put the “template” and “typename” keywords?。本质上,您需要告诉编译器在 List&lt;T&gt; 类中搜索名称 Item - 因此是 List&lt;T&gt;::Item - 您需要通过使用 typename 告诉它它是一种类型(而不是例如变量)。
猜你喜欢
  • 1970-01-01
  • 2011-10-20
  • 1970-01-01
  • 2018-04-19
  • 1970-01-01
  • 1970-01-01
  • 2020-09-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多