为 c++ 类重载 operator+。

Posted

技术标签:

【中文标题】为 c++ 类重载 operator+。【英文标题】:Overloading operator+ for c++ class. 【发布时间】:2012-05-03 12:56:22 【问题描述】:

我正在尝试为我的类实现 operator+(它必须连接来自同一类的两个对象的单链表),但程序给出错误:“lab5.exe 中 0x01351ca3 处的未处理异常:0xC0000005:访问冲突读取位置 0xcccccccc。” 奇怪的是它正确连接,因为我在 operator+ 中返回 temp 之前正在检查它(通过 //temp.print();)。

如果您能解释一下我的错误在哪里,我将不胜感激。代码如下:

#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;

    class list

    struct lista
    
        int num;
        char* word;
        lista* next;
    ;
    lista* head;
    char* name;
    public:
        list(char* name1)head=NULL;name=new char[strlen(name1)+1];strcpy(name,name1);
        char getChar(int key, int index);
        void setChar(int key, int index, char c);
        void insert(int number,char* txt);
        void remove(int number);
        void print();
        list(const list &o);
        list& operator=(const list &x);
        list& operator+(list &x);
        ~list();
    ;
    void list::insert(int number,char* txt)
        lista* ptr,*tmp;
            ptr=head;
        lista* newlista=new lista;
        newlista->num=number;
        newlista->next=NULL;
        newlista->word= new char[strlen(txt)+1];
        strcpy(newlista->word,txt);
        if(head==NULL)
            head=newlista;
            newlista->next=NULL;
        
        else while(ptr!=NULL)
                if(strcmp(txt,ptr->word)>=0)
                    if(ptr->next!=NULL && strcmp(txt,ptr->next->word)<=0)
                
                    tmp=ptr->next;
                    ptr->next=newlista;
                    newlista->next=tmp;
                    break;
                
                    else if(ptr->next!=NULL && strcmp(txt,ptr->next->word)>0)
                        ptr=ptr->next;
                    else
                     
                        //next is empty
                        ptr->next=newlista;
                        break;
                     
        
                else
                    //txt less than in 1st element
                    newlista->next=head;
                    head=newlista;
                    break;
                      
        
        return;
    

    void list::print()
        cout<<name<<";"<<endl;
        lista *druk;
        druk=head;
        while(druk!=NULL)
            cout<<"txt: "<<druk->word<<" | "<<"num: "<<druk->num<<endl;
            druk=druk->next;
        
        cout<<endl;
        return;
    


    void list::remove(int number)
        if(head==NULL)
            return;
        if(head->num==number)
            lista* ptr=head;
            head=head->next;
            delete [] ptr->word;
            delete ptr;
            return;
        
        lista* ptr=head;
        while(ptr->next!=NULL && ptr->next->num!=number)
            ptr=ptr->next;
        if(ptr->next==NULL)
            cout<<number<<" element not found"<<endl;
            return;
        
        lista* todelete=ptr->next;
        ptr->next=todelete->next;
        delete [] todelete->word;
        delete todelete;
        return;
    
    list::list(const list &o)
    
        lista *xtr = o.head;
        head=NULL;// without it doesn't work.
        lista *etr=head;// set etr on head?
        while (xtr)
        
    lista* ntr = new lista;
        if (!ntr)
            
    cerr << "list::CopyConstructor: Allocation memory failure!";
    cerr << endl;
    break;
            
    ntr->num = xtr->num;
    ntr->word= new char[strlen(xtr->word)+1];
    strcpy(ntr->word,xtr->word);
    ntr->next = NULL;
        if (head)
            etr->next = ntr;    
        else
            head = ntr;
    etr = ntr; // keep track of the last element in *this
    xtr = xtr->next;
        
    name = new char[strlen(o.name)+5];
    strcpy(name,o.name);
    strcat(name,"Copy");
    

    list& list::operator=(const list &x)
    
        if(this==&x)
            return *this;
        lista *etr=head;
        while(etr) // removing list from this
        
            etr=etr->next;
            delete head;
            head=etr;
        
        lista *xtr=x.head;
        while(xtr)
        
            int copied=xtr->num;
            lista *ntr= new lista;
            ntr->word=new char[strlen(xtr->word)+1];
            if (!ntr) 
                
    cerr << "list::operator=: Allocation memory failure!" << endl;
    break;
                
            ntr->num=copied;
            strcpy(ntr->word,xtr->word);
            ntr->next=NULL;
            if (!head)
                head = ntr;
            else
                etr->next = ntr;

                etr = ntr; // keep track of the last element in *this
                xtr = xtr->next;
    
    char *name=new char[strlen(x.name)+1];
    strcpy(name,x.name);
    return *this;
    

    list::~list()
    
        cout<<"Object with name:"<<name<<" destroyed!"<<endl;
        delete [] name;
        lista *dtr=head;
        while(dtr) // removing lista from this
        
            dtr=dtr->next;
            delete [] head->word;
            delete head;
            head=dtr;
        

    

    list& list::operator+(list &x)
    
        list temp(this->name);
        temp=*this;// using previously made operator= which creates the deep copy of singly linked list from this into temp;
        lista *xtr=x.head;
        while(xtr)
        
            temp.insert(xtr->num,xtr->word);
            xtr=xtr->next;
           
        //temp.print();
        return temp;
    
    int main()
        list l1("lista1");
        l1.insert(5,"Endian");
        l1.insert(7,"Endianness");
        l1.insert(100,"Hexediting");
        l1.insert(34,".mil");

        l1.print();
        list l2(l1); // usage of CC - the same as list l2=l1; 
        l2.print();
        l2.remove(5);
        l2.print();
        l1.print();

        list l3("asajnment");
            l3=l2=l1;
        l3.print();
        list l4("Testing+");
        l4.insert(155,"+++++++");
        l4.insert(144,"-----");
        l4.insert(111,"lalala");
        l4.print();
        l1=l4+l3;
        l1.print();
        getchar();
        return 0;
    

【问题讨论】:

恕我直言,有 operator+ 很奇怪,它返回 list&。语义上它类似于 operator+=,它应该修改它的 lhs。最好改名字,或者有list operator+,构造新对象。 Sample code 应该完整而简洁——足以重现问题,但仅此而已。发布的示例包含过多的无关代码。 【参考方案1】:

我认为你不应该在你的 operator+ 中返回一个引用

list list::operator+(list &x)
    
        list temp(this->name);
        temp=*this;// using previously made operator= which creates the deep copy of singly linked list from this into temp;
        lista *xtr=x.head;
        while(xtr)
        
            temp.insert(xtr->num,xtr->word);
            xtr=xtr->next;
           
        //temp.print();
        return temp;
    

如果您想返回评论中提到的链接参考:

list& list::operator+(list &x)
        
            lista *xtr=x.head;
            while(xtr)
            
                this->insert(xtr->num,xtr->word);
                xtr=xtr->next;
               
            return this;
        

这会将x 的值连接到您当前的对象。

您的编译器仍然应该警告您正在返回对临时对象的引用。

您还应该开始接受更多的答案,并考虑观众在看到您的帖子时的想法,您认为您发布的内容是否格式正确、信息丰富等?

【讨论】:

我返回引用是为了允许操作符链接,我的意思是a+b+c+d【参考方案2】:

您正在返回对临时对象的引用。这是不正确的。

当它被外部代码使用时,被引用的对象已经被销毁了。

【讨论】:

以上是关于为 c++ 类重载 operator+。的主要内容,如果未能解决你的问题,请参考以下文章

[C++] 类与对象(中) 一篇带你解决运算符重载实例--日期类Date

C++ operator关键字详解

如何在具有动态大小数组的模板类中重载 operator=

C++ 继承多态关系中的赋值运算符的重载=operator()

C++ 继承多态关系中的赋值运算符的重载=operator()

C++ 内存分配(new,operator new)详解