c ++ - 使用模板类重载的operator运算符

时间:2018-05-04 13:03:01

标签: c++

我正在尝试创建链接列表模板类。但是,在编译之后,我收到了这个错误

undefined reference to `std::ostream& operator<< <int>(std::ostream&,
Link_List<int> const&)
undefined reference to `std::istream& operator<< <int>(std::istream&,
Link_List<int> &)

以下是示例代码:

Link_List.h

#ifndef LINK_LIST
#define LINK_LIST

#include <iostream>
using namespace std;

template <typename T>
struct Int_Node
{
    T value;
    Int_Node<T> *pre, *next;
};

template <typename T>
class Link_List
{
    template <typename U>
    friend ostream &operator<<(ostream &, const Link_List<U> &);    // print all integers in the list
    template <typename U>
    friend istream &operator>>(istream &, Link_List<U> &);          // input a value at the back of the list, like insert_node(val);

public:
    Link_List();                                        // default constructor
    Link_List(const Link_List &);                       // copy constructor
    ~Link_List();
    int getSize() const;

    const Link_List &operator=(const Link_List &);      // assignment operator
    bool operator==(const Link_List &) const;           // equality operator
    bool operator!=(const Link_List &right) const       // inequality operator
    {
        return !(*this == right);
    }

    T &operator[](int index);                           // subscript operator for non-const objects
    T operator[](int index) const;                      // subscript operator for const objects

    bool insert_node(T value);                          // insert an integer at the back of link list
    bool delete_node();                                 // delete the last node
    bool insert_node(int index, T value);               // insert an integer after the i_th position
    bool delete_node(int index);                        // delete the i_th node

private:
    int size;
    Int_Node<T> *head, *tail;                               // pointer to the first and the last element of Link_List
};

#endif // LINK_LIST

implementation.cpp

#include <iostream>
#include "Link_List.h"

using namespace std;

template <typename T>
Link_List<T>::Link_List()
{ 
    head = tail = NULL;
    size = 0;
}

template <typename T>
Link_List<T>::Link_List(const Link_List &LL)
{
    Int_Node<T> *ptr1, *ptr2, *ptrPre;

    if (LL.head == NULL)
    {
        head = tail = NULL;
        size = 0;
    }
    else
    {
        head = new Int_Node<T>;

        head -> value = LL.head -> value;

        ptr1 = ptrPre = head;
        ptr2 = LL.head -> next;

        while (ptr2 != NULL)
        {
            ptr1 -> next = new Int_Node<T>;
            ptr1 = ptr1 -> next; // ptr1 to next node
            ptr1 -> value = ptr2 -> value;
            ptr1 -> pre = ptrPre;
            ptrPre = ptrPre -> next; // ptrPre to next node
            ptr2 = ptr2 -> next;
        } // next
        ptr1 -> next = NULL;
        tail = ptr1; // tail to the last node
        size = LL.size;
    } // generate node
}

template <typename T>
Link_List<T>::~Link_List()
{
}

template <typename T>
ostream &operator<<(ostream &os, const Link_List<T> &LL)
{
    Int_Node<T> *ptr;
    ptr = LL.head;
    while (ptr != NULL)
    {
        os << ptr -> value << " ";
        ptr = ptr -> next;
    }
    os << endl;
    delete ptr;

    return os;
}

template <typename T>
istream &operator>>(istream &is, Link_List<T> &LL)
{
    Int_Node<T> *ptr;

    if (LL.head == NULL)
    {
        LL.head = LL.tail = new Int_Node<T>;

        is >> LL.head -> value;
        LL.size++;
    }
    else
    {
        ptr = LL.head;

        LL.tail -> next = new Int_Node<T>;
        LL.tail = LL.tail -> next;
        LL.tail -> pre = ptr;
        ptr = ptr -> next;
        LL.tail -> next = NULL;

        is >> LL.tail -> value;
        LL.size++;
    }

    return is;
}

template <typename T>
int Link_List<T>::getSize() const
{
    return size;
}

template <typename T>
const Link_List<T> &Link_List<T>::operator=(const Link_List<T> &LL)
{
    Int_Node<T> *ptr1, *ptr2, *ptrPre;

    if (LL.head == NULL)
    {
        head = tail = NULL;
        size = 0;
    }
    else
    {
        head = new Int_Node<T>;

        head -> value = LL.head -> value;

        ptr1 = ptrPre = head;
        ptr2 = LL.head -> next;

        while (ptr2 != NULL)
        {
            ptr1 -> next = new Int_Node<T>;
            ptr1 = ptr1 -> next; // ptr1 to next node
            ptr1 -> value = ptr2 -> value;
            ptr1 -> pre = ptrPre;
            ptrPre = ptrPre -> next; // ptrPre to next node
            ptr2 = ptr2 -> next;
        } // next
        ptr1 -> next = NULL;
        tail = ptr1; // tail to the last node
        size = LL.size;
    } // generate node

    return *this;
}

template <typename T>
bool Link_List<T>::operator==(const Link_List<T> &LL) const
{
    Int_Node<T> *ptr1, *ptr2;

    ptr1 = head;
    ptr2 = LL.head;
    while (ptr1 != NULL)
    {
        if (ptr1 -> value != ptr2 -> value)
            return false;
        ptr1 = ptr1 -> next;
        ptr2 = ptr2 -> next;
    }
    return true;
}

//template <typename T>
//bool Link_List<T>::operator!=(const Link_List<T> &right) const
//{
//  Int_Node<T> *ptr1, *ptr2;
//  
//  ptr1 = head;
//  ptr2 = right.head;
//  while (ptr1 != NULL)
//  {
//      if (ptr1 -> value != ptr2 -> value)
//          return true;
//      ptr1 = ptr1 -> next;
//      ptr2 = ptr2 -> next;
//  }
//  return false;
//}

template <typename T>
T &Link_List<T>::operator[](int index)
{
    int count = 0;
    Int_Node<T> *ptr;

    ptr = head;
    while (count < index - 1)
    {
        ptr = ptr -> next;
        count++;
    }

    return ptr -> value;
}

template <typename T>
T Link_List<T>::operator[](int index) const
{
    int count = 0;
    Int_Node<T> *ptr;

    ptr = head;
    while (count < index - 1)
    {
        ptr = ptr -> next;
        count++;
    }

    return ptr -> value;    
}

template <typename T>
bool Link_List<T>::insert_node(T value)
{
    Int_Node<T> *ptr;

    if (head == NULL)
    {
        head = tail = new Int_Node<T>;
        head -> pre = NULL;
        head -> value = value;
        head -> next = NULL; 
    } // if no node
    else
    {
        ptr = tail;
        tail -> next = new Int_Node<T>;
        tail = tail -> next; // to next
        tail -> value = value;
        tail -> pre = ptr;
        tail -> next = NULL;

        ptr = ptr -> next;
    }
    size++;
    return true;
}

template <typename T>
bool Link_List<T>::delete_node()
{
    if (head != NULL)
    {
        if (tail -> pre != NULL)
        {
            tail = tail -> pre;
            tail -> next = NULL;
        }
        else
        {
            head = tail = NULL;
        }
        size--;
        return true;
    }
    else
    {
        size--;
        return false;
    }
}

template <typename T>
bool Link_List<T>::insert_node(int index, T value)
{
    if (index > size)
        return false;

    int count = 0;
    Int_Node<T> *ptr, *node;

    ptr = head;
    while (count < index - 1)
    {
        ptr = ptr -> next;
        count++;
    }

    if (ptr -> next != NULL)
    {
        node = new Int_Node<T>;
        node -> pre = ptr;
        node -> value = value;
        node -> next = ptr -> next;
        ptr -> next = node;
    } // not the last node
    else
    {
        node = new Int_Node<T>;
        node -> pre = tail;
        node -> value = value;
        node -> next = NULL;
        tail = node;
    } // last node
    return true;
}

template <typename T>
bool Link_List<T>::delete_node(int index)
{
    if (index > size)
        return false;

    int count = 0;
    Int_Node<T> *ptr;

    ptr = head;
    while (count < index - 1)
    {
        ptr = ptr -> next;
        count++;
    }
    ptr -> next = ptr -> next -> next; // skip the next node

    return true;
}    
template class Int_Node<char>;
template class Int_Node<float>;
template class Int_Node<int>;

template class Link_List<char>;
template class Link_List<float>;
template class Link_List<int>;

的main.cpp

#include <iostream>

#include "Link_List.h"

using namespace std;

int main()
{

    // test default constructor
    Link_List<int> linkList1;

    // test copy constructor
    Link_List<int> linkList2(linkList1);

    // test getSize()
    cout << "linkList2 Size: " << linkList2.getSize() << endl;

    // test insert_node(value), delete_node(), operator<<, operator>>

    Link_List<int> linkList3;
    cout << "Enter a integer: ";
    cin >> linkList3;
    cout << "linkList3: "<< linkList3 << endl;

    linkList3.insert_node(11);
    linkList3.insert_node(12);
    linkList3.insert_node(13);
    linkList3.insert_node(14);
    linkList3.insert_node(15);
    cout << "Insert Boolean: " << linkList3.insert_node(16) << endl;
    cout << "linkList3: " << linkList3 << endl;

    cout << "Delete Boolean: " << linkList3.delete_node() << endl;
    cout << "linkList3: " << linkList3 << endl;

    // test assignment operator, equality operator, insert_node(index, value), delete_node(index)
    Link_List<int> linkList4 = linkList3;
    cout << "linkList4: " << linkList4 << endl;

    cout << "Insert Boolean: " << linkList4.insert_node(3, 17) << endl;
    cout << "linkList4: " << linkList4 << endl;

    cout << "Delete Boolean: " << linkList4.delete_node(4) << endl;
    cout << "Equality Boolean: " << (linkList4==linkList3) << endl;
    cout << "linkList4: " << linkList4 << endl;

    // test subscript operator []
    const Link_List<int> linkList5 = linkList4;
    cout << "linkList4[1]: " << linkList4[1] << endl;
    cout << "linkList5[1]: " << linkList5[1] << endl;

    return 0;
}

我不确定错误是来自编译器还是我的代码。

我已根据这篇文章overloading friend operator<< for template class尝试过外向和内向的方法,但都没有奏效。我该如何才能让它在我的案例中发挥作用?

编辑:将显式实例移动到implementation.cpp

的末尾

编辑:它在我添加以下实例

时起作用
template ostream& operator<<(ostream &, const Link_List<char> &);
template ostream& operator<<(ostream &, const Link_List<float> &);
template ostream& operator<<(ostream &, const Link_List<int> &);

template istream &operator>>(istream &, Link_List<char> &);
template istream &operator>>(istream &, Link_List<float> &);
template istream &operator>>(istream &, Link_List<int> &);

1 个答案:

答案 0 :(得分:1)

小伙伴,您可以将operator>>operator<<定义放在.h文件中,如下所示:

#ifndef LINK_LIST
#define LINK_LIST

#include <iostream>
using namespace std;
template <typename T>
struct Int_Node
{
    T value;
    Int_Node<T> *pre, *next;
};

template <typename T>
class Link_List
{
    friend ostream &operator<<(ostream &os, const Link_List<T> &LL)
      {
        Int_Node<T> *ptr;
        ptr = LL.head;
        while (ptr != NULL)
          {
            os << ptr -> value << " ";
            ptr = ptr -> next;
          }
        os << endl;
        delete ptr;

        return os;
}
    friend istream &operator>>(istream &is, Link_List<T> &LL)
      {
        Int_Node<T> *ptr;

        if (LL.head == NULL)
          {
            LL.head = LL.tail = new Int_Node<T>;

            is >> LL.head -> value;
            LL.size++;
          }
        else
          {
            ptr = LL.head;

            LL.tail -> next = new Int_Node<T>;
            LL.tail = LL.tail -> next;
            LL.tail -> pre = ptr;
            ptr = ptr -> next;
            LL.tail -> next = NULL;

            is >> LL.tail -> value;
            LL.size++;
          }

        return is;
}
public:
    Link_List();                                        // default constructor
    Link_List(const Link_List &);                       // copy constructor
    ~Link_List();
    int getSize() const;

    const Link_List &operator=(const Link_List &);      // assignment operator
    bool operator==(const Link_List &) const;           // equality operator
    bool operator!=(const Link_List &right) const       // inequality operator
    {
        return !(*this == right);
    }

    T &operator[](int index);                           // subscript operator for non-const objects
    T operator[](int index) const;                      // subscript operator for const objects

    bool insert_node(T value);                          // insert an integer at the back of link list
    bool delete_node();                                 // delete the last node
    bool insert_node(int index, T value);               // insert an integer after the i_th position
    bool delete_node(int index);                        // delete the i_th node

private:
    int size;
    Int_Node<T> *head, *tail;                               // pointer to the first and the last element of Link_List
};

#endif // LINK_LIST

然后,它可以愉快地编译:)

当然,您也可以在template U中使用.h(但此处不推荐)

#ifndef LINK_LIST
#define LINK_LIST

#include <iostream>
using namespace std;
template <typename T>
struct Int_Node
{
    T value;
    Int_Node<T> *pre, *next;
};

template <typename T>
class Link_List
{
    template< typename U>
    friend ostream &operator<<(ostream &os, const Link_List<U> &LL)
      {
        Int_Node<T> *ptr;
        ptr = LL.head;
        while (ptr != NULL)
          {
            os << ptr -> value << " ";
            ptr = ptr -> next;
          }
        os << endl;
        delete ptr;

        return os;
    }
    template<typename U>
    friend istream &operator>>(istream &is, Link_List<U> &LL)
      {
        Int_Node<T> *ptr;

        if (LL.head == NULL)
          {
            LL.head = LL.tail = new Int_Node<T>;

            is >> LL.head -> value;
            LL.size++;
          }
        else
          {
            ptr = LL.head;

            LL.tail -> next = new Int_Node<T>;
            LL.tail = LL.tail -> next;
            LL.tail -> pre = ptr;
            ptr = ptr -> next;
            LL.tail -> next = NULL;

            is >> LL.tail -> value;
            LL.size++;
          }

        return is;
}
public:
    Link_List();                                        // default constructor
    Link_List(const Link_List &);                       // copy constructor
    ~Link_List();
    int getSize() const;

    const Link_List &operator=(const Link_List &);      // assignment operator
    bool operator==(const Link_List &) const;           // equality operator
    bool operator!=(const Link_List &right) const       // inequality operator
    {
        return !(*this == right);
    }

    T &operator[](int index);                           // subscript operator for non-const objects
    T operator[](int index) const;                      // subscript operator for const objects

    bool insert_node(T value);                          // insert an integer at the back of link list
    bool delete_node();                                 // delete the last node
    bool insert_node(int index, T value);               // insert an integer after the i_th position
    bool delete_node(int index);                        // delete the i_th node

private:
    int size;
    Int_Node<T> *head, *tail;                               // pointer to the first and the last element of Link_List
};

#endif // LINK_LIST
相关问题