在模板链表中使用友元函数时出现链接错误

发布于 2024-12-21 11:52:41 字数 1431 浏览 4 评论 0原文

我编写了一个模板链接列表(在 .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);

I programmed a template linked list(in .h file) and I get link error.

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

For some reason the link error disappears when I write instead in the declaration of the friend function in the class:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心意如水 2024-12-28 11:52:41

事情是这样的:您声明的朋友不是模板,因此您的 << 的给定实例化是template 不是您声明为朋友的模板。

如果您像这样声明好友

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

,则 operator << 将是 LinkedList 的友元。如果这是不可取的,可以采用以下解决方案:

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

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

这篇文章详细解释了该主题

Here's the thing: the friend you declared is not a template, so the given instantiation of your << template isn't the one you declared friend.

If you declare the friend like this

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

then operator << <int> will be a friend of LinkedList<float>. If that is undesirable, there is this solution:

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

In this case, only the particular instantiation of the template is your friend, which might be what you need.

This article explains the topic in detail

请恋爱 2024-12-28 11:52:41

因为类外部的operator<<定义实际上是一个函数模板,而类内部的友元声明则不是函数模板。

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<< 的定义一致,这也是一个函数模板。但有一个问题:它使函数模板的每个特化成为类的友元;意味着当U=float时,operator<<也可以访问LinkedList的私有成员,当它应该能够仅访问 LinkedList 的私有成员。所以你看,这就是问题所在。

更好的解决方案是:不要使其成为函数模板,并在类本身内部定义友元。

template<typename T>
class LinkedList
{
  public:


  friend ostream& operator << (ostream& out, const LinkedList<T>& that)
  {
      //definition 
  }
};

Because the definition of operator<< outside the class is actually a function template, whereas the friend declaration inside the class is not function template.

The friend declaration is a non-template function, and its arguments are fixed with respect to the class template.

For example, if you instantiate the class template with int, then the friend becomes this:

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

which tells the compiler that "I'm a friend of this class, I'm also a non-template function and you will find my defintion outside the class, exactly with same signature.". You can see the arguments are fixed.

But when you do something like this:

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

It makes sense to the compiler, as it is consistent with the definition of operator<< outside the class, which is also a function template. But there is a problem: it makes every specialization of the function template a friend of the class; means when U=float, the operator<< can access private members of LinkedList<int> as well, when it should be able to access private members of LinkedList<float> ONLY. So you see, this is the problem.

A better solution would be this: DO NOT make it function template, and define the friend inside the class itself.

template<typename T>
class LinkedList
{
  public:


  friend ostream& operator << (ostream& out, const LinkedList<T>& that)
  {
      //definition 
  }
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文