基本深层复制(op重载)

时间:2015-01-31 00:00:30

标签: c++ inheritance deep-copy

我正在创建一个简单的类 Person ,它继承自抽象类 Object 。我正处于我正在学习深层复制的部分,但我似乎无法使用这段简单的代码:

Person.h

#include <iostream>
#include <cstring>  
#ifndef _PERSON_H_
#define _PERSON_H_
using namespace std;


class Object {
protected:
    //This pure virtual func. sends appropriate  ostream
    //to operator<<'s override. Must be implemented in each
    //derived class accordingly.
    virtual void print(std::ostream&) const =0;
public:
    //Override ostream operator.
    friend ostream& operator<<(ostream& os, const Object& obj);
    friend ostream& operator<<(ostream& os, const Object* obj);
    virtual ~Object();
};

class Person : public Object {
private:
    char* m_name;
    virtual void print(std::ostream& os) const;
    Person(); //What's your default name?
public:
    Person(char* name);
    Person(const Person& p);
    Person& operator=(const Person &rhs);
    virtual ~Person();
};

#endif // _PERSON_H_

Person.cpp

#include "Person.h"


ostream& operator<<(ostream& os, const Object& obj) {
    obj.print(os);
    return os;
}

ostream& operator<<(ostream& os, const Object* obj) {
    obj->print(os);
    return os;
}
Object::~Object() { };

//Standard ctor
Person::Person(char* name) {
    m_name = new char[strlen(name)];
    strncpy(m_name, name, strlen(name));
}
//Copy ctor
Person::Person(const Person& p) {
    m_name = new char[strlen(p.m_name)];
    strncpy(m_name, p.m_name, strlen(p.m_name));
}


//dtor
Person::~Person() {
    delete [] m_name;
}
//operator= overload
Person& Person::operator=(const Person &rhs) {
    if (this == &rhs) return * this; //Self copy check.
    delete [] m_name;
    m_name = new char[strlen(rhs.m_name)];
    strncpy(m_name, rhs.m_name, strlen(rhs.m_name));
    return * this;
}

//private
void Person::print(std::ostream& os) const{
    os << m_name;
}

int main() {
    //Person p1("Anis");
    //Person p2("Bassam");
    Person * p1 = new Person("Anis");
    Person * p2 = new Person("Bassam");
    p1 = p2;
    delete p1; 
    delete p2;
    return 0;
}

输出:

a.out(4839,0x7fff7420b300) malloc: *** error for object 0x7f914b404ad0: pointer being freed was not allocated

gdb bt:

#0  0x00007fff8d7b2282 in __pthread_kill ()
#1  0x00007fff8b5fd4c3 in pthread_kill ()
#2  0x00007fff8e528b73 in abort ()
#3  0x00007fff83739937 in free ()
#4  0x0000000100000b51 in Person::~Person (this=0x1001048e0) at Person.cc:29
#5  0x0000000100000b85 in Person::~Person (this=0x1001048e0) at Person.cc:28
#6  0x0000000100000ba8 in Person::~Person (this=0x1001048e0) at Person.cc:28
#7  0x0000000100000e46 in main () at Person.cc:54

根据 gdb ,程序在 delete p2; 上崩溃。在书中他们警告我们这种情况,所以我按照他们提供的修复,这是重载 operator = 并确保有复制ctor。 我错过了什么?提前谢谢。

P.S。我目前只对深层复制问题感兴趣。模板和泛型将在后面的章节中介绍。

3 个答案:

答案 0 :(得分:3)

p1=p2之后,两个变量都指向同一个对象。 delete p1删除此对象。因此delete p2会再次尝试删除此对象。

当您指定指针而不是对象时,Operator =无法帮助您。你可能想要*p1 = *p2

答案 1 :(得分:2)

可能存在其他错误,但至少在strlenm_nameos << m_name;上调用m_name = new char[strlen(name)]; 时,您会有未定义的行为,因为您没有预留足够的空间对于以null结尾的字符串。这种分配是错误的:

m_name = new char[strlen(name) + 1];

你需要

{{1}}

允许空终止符。您还必须确保设置了空终止。

答案 2 :(得分:2)

你认为这一行使用你的Person :: operator = function吗?它没有。这一行处理对象的指针而不是对象本身(即,这是简单的指针赋值)。

p1 = p2;

以下行将调用您的Person :: operator = function。

*p1 = *p2;

我不确定你收到错误的原因。我猜想你会收到一些关于双重​​免费/删除的内容。