【问题标题】:Link error when using friend function in template linkedlist在模板链表中使用友元函数时链接错误
【发布时间】:2011-12-17 14:49:28
【问题描述】:

我编写了一个模板链表(在 .h 文件中),但出现链接错误。

template <typename T>
class LinkedList
{
private:
    Node<T>* head;
    Node<T>* tail;
    int size;

public:
    LinkedList();
    ~LinkedList();
    inline T* Front() {return &(this->head);};
    inline const T* Front() const {return (const T*)this->head;};
    void InsertFirst(const T&);
    void InsertLast(const T&);
    void RemoveFirst();
    void RemoveLast ();
    void RemoveItem (const T&);
    void Sort();
    void Clear();
    inline bool Exists(const T&) const;
    bool Empty() const {return this->size==0 ? true : false;};
    inline int Size() const {return this->size;};
    T* At(const int index);
    const T* At(int index) const; 
    friend ostream& operator << (ostream& out, const LinkedList<T>& that);
    T* operator[](const int);
    const T* operator[](const int) const;   
};
.
.
.

template <typename T>
ostream& operator << (ostream& out, const LinkedList<T>& that)
{
    if (!that.Empty())
        for(Node<T>* seeker=that.head; seeker; seeker=seeker->next)
            out<<seeker->info<<endl;
    return out;
}

由于某种原因,当我改为在类中的朋友函数声明中编写时,链接错误消失了:

template <typename T> friend ostream& operator << (ostream& out, const LinkedList<T>& that);

【问题讨论】:

  • 看来你自己回答了...

标签: c++ templates linked-list linker-errors friend


【解决方案1】:

事情是这样的:你声明的朋友不是模板,所以你的

如果你这样声明朋友

template <typename U> //or T, doesn't matter
friend ostream& operator << (ostream& out, const LinkedList<U>& that);

那么operator &lt;&lt; &lt;int&gt; 将成为LinkedList&lt;float&gt; 的朋友。如果这是不可取的,有这个解决方案:

friend ostream& operator <<<T> (ostream& out, const LinkedList<T>& that);

在这种情况下,只有模板的特定实例是您的朋友,这可能是您需要的。

This article详细讲解题目

【讨论】:

    【解决方案2】:

    因为operator&lt;&lt;在类外的定义其实是一个函数模板,而类内的friend声明不是函数模板。

    friend 声明是一个非模板函数,它的参数相对于类模板是固定的。

    例如,如果您使用int 实例化类模板,则friend 变为:

    friend ostream& operator << (ostream& out, const LinkedList<int>& that);
    

    它告诉编译器“我是这个类的朋友,我也是一个非模板函数,你会在类之外找到我的定义,完全一样的签名。”。 你可以看到参数是固定的。

    但是当你做这样的事情时:

    template <typename U>
    friend ostream& operator << (ostream& out, const LinkedList<U>& that);
    

    这对编译器来说是有意义的,因为它与类外的operator&lt;&lt; 的定义是一致的,这也是一个函数模板。但是有一个问题:它使函数模板的每个特化都成为类的朋友;表示当U=float 时,operator&lt;&lt; 也可以访问LinkedList&lt;int&gt; 的私有成员,但它应该只能访问LinkedList&lt;float&gt; 的私有成员。所以你看,这就是问题所在。

    更好的解决方案是:不要将其设为函数模板,并在类本身中定义朋友。

    template<typename T>
    class LinkedList
    {
      public:
    
    
      friend ostream& operator << (ostream& out, const LinkedList<T>& that)
      {
          //definition 
      }
    };
    

    【讨论】:

      猜你喜欢
      • 2017-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-13
      相关资源
      最近更新 更多