c++ - 在类模板(链接列表)中重载运算符

标签 c++ templates linked-list operator-overloading

注意:这是作业

特别是我的问题是 + 赋值运算符,我正在编写一个单链表模板并且必须创建运算符 +=、+、-、[] 等。到目前为止,我已经编写了数组和 +=,没有太大问题,但现在我正在处理 + 运算符 目前我有...

队列.h

#ifndef QUEUE_H
#define QUEUE_H

#include<iostream>
//#include "UnderGrad.h"
//#include "Grad.h"
#include <string.h>
#include<cstdlib>

template <typename T>
class Queue
{
class Node
{
    friend class Queue;
    private:
    T* data;
    Node* next;
};

public:
    Queue() {head = NULL; tail = NULL; numNodes = 0;}
    ~Queue () {clear();}

    //overloaded operators
    T& operator [] (int);
    const T& operator [] (int) const;
    Queue<T>& operator += (T*);
    Queue<T>& operator += (Queue<T>&);
    friend Queue<T> operator+ (Queue<T> inList,T* tbAdded)
    {
        inList.pushBack(tbAdded);

        return inList;
    }
    //Queue<T> operator + (Queue<T>, Queue<T>&);
    //Queue<T>& operator -= (T*&);
    //Queue<T>& operator -= (const Queue<T>&);
    //Queue<T> operator - (T, const T&);
    //Queue<T> operator -(Queue<T>, const Queue<T>&);
    //Queue<T>& operator ! ();



    void pushBack(T*);
    //nice to be ble to clear all sometimes rather than write a for loop evertime you want ot clear the list
    void clear();
    void popFront();

    bool empty();
    T* front();
    int size() const;

    //used while an individual is using create app, so you can go back and edit prevous pages of the app
    T* getPrev(T*);
    T* back();
    void removeNode(T*);
    void sortList();

private:
Node* head;
Node* tail;
int numNodes;

};


//be carefule here with automatic variables
//as it will not create a new instance
template <typename T>
Queue<T>& Queue<T>::operator += (T* tbAdded)
{
    this -> pushBack(tbAdded);
return *this;
}


template <typename T>
Queue<T>& Queue<T>::operator += (Queue<T> &tbAdded)
{   
T* temp;

while (tbAdded.front() != NULL)
{
    temp = (T*) new T(*(tbAdded.front()));
    this -> pushBack(temp);
    tbAdded.popFront();
}

return *this;
}

template <typename T>
const T& Queue<T>::operator[] (int index) const
{
int count = 0;
Node *temp = head;

while (count < index && temp -> next != NULL)
{
    count++;
    temp = temp -> next;
}

if (count < index)
{
    std::cerr << "ArrayOutOfBounds: Index at: " << index << " ArrayLength: " << count << std::endl;
    exit(1);
}
else
{
    return *(temp -> data);
}
}

template <typename T>
T& Queue<T>::operator[] (int index)
{
int count = 0;
Node *temp = head;

while (count < index && temp -> next != NULL)
{
    count++;
    temp = temp -> next;
}

if (count < index)
{
    std::cerr << "ArrayOutOfBounds: Index at: " << index << " ArrayLength: " << count << std::endl;
    exit(1);
}
else
{
    return *(temp -> data);
}
}



//adds node to the back of the list
template <typename T>
void Queue<T>::pushBack(T *tbAdded)
{
    //  std::cout << "hello" << std::endl;

Node *temp = new Node;
//I copy the data into the heap, because for some operations i want to use save   local variables which poses problematic
temp -> data = tbAdded;
temp -> next  = NULL;
    //  std::cout << "hello" << std::endl;
if (head == NULL)
{
    //  std::cout << "bye" << std::endl;
    head = temp;
    tail = head;
}   
else
{
    //  std::cout << "shy" << std::endl;
    tail -> next = temp;
    tail = tail -> next;

}
    //  std::cout << "hello" << std::endl;
numNodes++;
}

//returns length of Queue
template <typename T>
int Queue<T>::size() const
{
return numNodes;
}


//removes a node formt he fornt of the list
template <typename T>
void Queue<T>::popFront()
{
if (head != NULL)
{
    Node *temp = head;
    head = head ->next;
    delete (temp -> data);
    delete (temp);
    numNodes--;
    if (numNodes > 0)
    {
        numNodes--;
        if (numNodes == 0)
        {
            tail = NULL;
        }
    }
}
}

//clears the list
template <typename T>
void Queue<T>::clear()
{
while (head != NULL)
{
    popFront();
}
}

//returns true iff list is empty
template <typename T>
bool Queue<T>::empty()
{
if (numNodes == 0)
{
    return true;
}

return false;
}


//returns data at fornt of list unless the list is empty then it returns null
template <typename T>
T* Queue<T>::front()
{
if (head != NULL)
{
    return head -> data;
}
else
{
    return NULL;
}
}

 //sorts undgrad info
//template <>
//inline void Queue<UnderGrad>::sortList()
//{
//  Node *temp = head;
//  UnderGrad *info;
//
//  for (int i = 0; i < size(); i++)
//  {
//      while (temp -> next)
//      {
//          std::string temp1 = (*(temp -> data)).getCourse();
//          std::string temp2 = (*(temp -> next -> data)).getCourse();
//          if (strcmp(temp1.c_str(), temp2.c_str()) > 0)
//          {
//              info = temp -> data;
//              temp -> data = temp -> next -> data;
//              temp -> next -> data = info;
//
//          }
//          else if (strcmp(temp1.c_str(), temp2.c_str()) == 0 && 
//              (*(temp -> data)).getGPA() < (*(temp -> next -> data)).getGPA())
//          {
//              info = temp -> data;
//              temp -> data = temp -> next -> data;
//              temp -> next -> data =    info;                 
//          }
//
//          temp = temp -> next;
//      }
//      
//      temp = head;
//  }
//  
//
//  
//}


//sorts Grad info
//template <>
//inline void Queue<Grad>::sortList()
//{
//  Node *temp = head;
//  Grad *info;
//
//  for (int i = 0; i < size(); i++)
//  {
//      while (temp -> next)
//      {
//          std::string temp1 = (*(temp -> data)).getCourse();
//          std::string temp2 = (*(temp -> next -> data)).getCourse();
//          std::string temp3 = (*(temp -> data)).getResearch();
//          std::string temp4 = (*(temp -> next -> data)).getResearch();
//          if (strcmp(temp1.c_str(), temp2.c_str()) > 0)
//          {
//              info = temp -> data;
//              temp -> data = temp -> next -> data;
//              temp -> next -> data = info;
//
//          }
//          else if (strcmp(temp1.c_str(), temp2.c_str()) == 0 && 
//              strcmp(temp3.c_str(), temp4.c_str()) > 0)
//          {
//              info = temp -> data;
//              temp -> data = temp -> next -> data;
//              temp -> next -> data = info;                    
//          }
//
//          temp = temp -> next;
//      }
//      temp = head;
//  }
//  
//
//  
//}


//these mothds i was considering using for a bonus but never completed they are used   no where in my code for now atleast
//this method is used when a back button is pressed so i can go from end to front of a list (since this is supposed to be a singly linked list this will be inneficient)
//that way if i have multiple things i.e related courses saved i can go back and edit  them b4 i save the app
template <typename T>
T* Queue<T>::getPrev(T* curNode)
{
if (curNode == head)
{
    return NULL;
}

Node *temp = head;
while (temp -> next != curNode)
{
    temp = temp -> next;
}

return temp -> data;
}


//if editing data i need a acces the last node in order to be able to go back and eit nodes back -> front
template <typename T>
T* Queue<T>::back()
{
if (tail != NULL)
{
    return head -> data;
}
else
{
    return NULL;
}
}

//if we decide to go back and edit we will need to remove the old node
template <typename T>
void Queue<T>::removeNode(T *tbRemoved)
{
Node *curNode, *prevNode;

curNode = head;

if (tbRemoved == head -> data)
{
    head = head -> next;
    delete curNode -> data;
    delete curNode;
}

while (curNode -> data != tbRemoved)
{
    prevNode = curNode;
    curNode = curNode -> next;
}

prevNode -> next = curNode -> next;
delete curNode -> data;
delete curNode;
}

#endif 

主要.cpp

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

using namespace std;

int main()
{
Queue<int> intList;
Queue<int> intList1, intList2;
int *t;

intList.pushBack((int*) new int (5));
intList.pushBack((int*) new int (10));
intList.pushBack((int*) new int (15));
intList.pushBack((int*) new int (20));


intList += ((int*) new int (25));
cout << intList[4] << "!" << endl;
cout << "?" << endl;
cout << "?" << endl;
cout << "?" << endl;
intList = intList + ((int*) new int (35));
cout << intList[5] << "!" << endl;
intList += ((int*) new int (30));
cout << intList[5] << "!" << endl;
cout << "?" << endl;
cout << "?" << endl;
cout << "?" << endl;

intList1.pushBack((int*) new int (2));
intList1.pushBack((int*) new int (7));
intList1.pushBack((int*) new int (9));
intList1.pushBack((int*) new int (11));
intList += intList1;
    intList1.clear();
cout << intList[6] << "!" << endl;
cout << intList[2] << "!" << endl;
intList.clear();
intList1.clear();
cout << "?" << endl;


Queue<string> strList;
cout << "?" << endl;    
strList.pushBack((string*) new string("hi"));
strList.pushBack((string*) new string("bi"));
strList.pushBack((string*) new string("di"));
strList.pushBack((string*) new string("ki"));
cout << "?" << endl;
cout << strList[2] << "!" << endl;
return 0;
}

输出: 25!

?

?

?

段错误(核心转储)

我需要实现 + 运算符,以便它接受一个数据指针并返回一个由旧列表和新节点组成的新列表,我在类模板本身中编写了这个函数,因为我读到写它是一个问题外面,就像我的其他功能一样。 我尝试了几种方法来让它工作

  • 使用我定义的 += 赋值运算符(加上等于可以正常工作,但是当我将它与他的函数一起使用时出现问题?)

  • 我尝试创建一个新列表并用旧数据和新数据填充它,然后返回该列表,但没有用..所以现在我很困惑,在正确的方向上找到一个点会很棒!


编辑: 我已经尝试从类定义中删除我的 + 运算符并将其减少为接受一个参数

template <typename T>
Queue<T>& Queue<T>::operator+ (T* tbAdded)
{
Queue<T> *temp = (Queue<T> *) new Queue<T>(*this);
temp -> pushBack(tbAdded);
  //    std::cout << (*temp)[5] << std::endl;
  //    std::cout << (*this)[3] << std::endl;
return *temp;
}

形成我对它的所有测试,这似乎“有效”但是在我的测试结束时(在所有输出正确输出之后)有一个段错误

最佳答案

您需要为您的类定义一个复制构造函数和一个赋值运算符。这些将需要逐个元素地复制整个列表。

在下面的代码中:

Queue<T> *temp = (Queue<T> *) new Queue<T>(*this);

Queue<T>(*this)调用复制构造函数。由于您不提供,编译器会为您生成一个。该自动生成的复制构造函数只是对您的对象进行逐字段复制。换句话说,它复制了 head。和 tail 指针,以及 numNodes 的值.

然而,这是错误的,因为当原始元素和拷贝超出范围时,它们都会尝试释放相同的元素。这会导致未定义的行为,并解释您所看到的崩溃。

参见 Rule of Three .

关于c++ - 在类模板(链接列表)中重载运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15457687/

相关文章:

c++ - Win32 C++ Alphablend 位图部分透明

c++ - 将 std::vector 传递给数组引用

C++ : Any possibility to declare a struct in main. cpp 但在 header 中有一个带有类的模板

c - 在c中将封装的动态大小的数据写入文本文件

c++ - QSqlquery prepare() 和 bindvalue() 不工作?

node.js - Nodejs 模板系统文档

javascript - Meteor - 从子助手访问父模板变量

c - 将文本文件读入链表

c - 在 C 中显示相同数字的简单链表

c++ - 管理生成文件中的依赖关系复杂性