Deep Copy构造函数中的问题

时间:2012-12-06 05:52:00

标签: c++ visual-studio-2010 pointers constructor

请查看以下代码

Location.h

#pragma once
class Location
{
public:
    Location(void);
    Location(int,int,int);
    ~Location(void);
    Location(const Location *loc);

    void display();
    void set(int,int,int);

private:

    int x,y,z;
};

Location.cpp

#include "Location.h"
#include <iostream>
#include <string>

using namespace std;


Location::Location()
{
}

Location::Location(int x,int y, int z)
{
    set(x,y,z);
}



Location::~Location(void)
{
}


void Location::display()
{
    cout << "X: " << x << endl;
    cout << "Y: " << y << endl;
    cout << "Z: " << z << endl;
}

void Location::set(int xx,int yy,int zz)
{
    x = xx;
    y = yy;
    z = zz;
}

Object.h

#pragma once
#include "Location.h"

class GameObject
{
public: 
    GameObject(int);
    ~GameObject(void);
    GameObject(int,Location *);
    GameObject(const GameObject *obj);

    Location *location;

    int getNumberOfObjects();

    static int counter;


    int id;

private:
    GameObject(void);



};

Object.cpp

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

using namespace std;

static int counter = 0;

int GameObject::counter = 0;

GameObject::GameObject(void)
{
}

GameObject::GameObject(int i)
{
    counter++;
    id = i;
}

GameObject::GameObject(int i,Location *loc)
{
    id = i;
    location = loc;
}

GameObject::GameObject(const GameObject *ob)
{
    this->location = new Location(ob->location);
}


GameObject::~GameObject(void)
{
}

Main.cpp的

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

using namespace std;

int main()
{
    //GameObject obj1;
    //cout << obj1.id << endl;

    GameObject obj2(45);
    cout << obj2.id << endl;;
//  cout << obj2.counter << endl; 

    //Declaring dynamic objects for Location
    Location *loc1 = new Location(1,1,1);
    Location *loc2 = new Location(2,2,2);
    Location *loc3 = new Location(3,3,3);


    //Assigning each GameObject a location
    GameObject obj3(45,loc1);
    GameObject obj4(45,loc2);
    GameObject obj5(45,loc3);

    //Displaying Number of GameObject objects
    cout << "Number of Objects: " << GameObject::counter << endl;

    //Invoking Location's display() method using GameObject objects
    cout << "......obj3 values........" << endl;
    obj3.location->display();
    cout << "......obj4 values........" << endl;
    obj4.location->display();
    cout << "......obj5 values........" << endl;
    obj5.location->display();


    //Declaring new Static GameObject
    GameObject obj6(obj4);

    //Invoking display() member function using both obj4 and obj6 GameObjects
    cout << endl;
    cout << "Invoking display() member function using both obj4 and obj6 GameObjects " << endl;
    obj4.location->display();
    obj6.location->display();

    //Changing the location values in obj4
    obj4.location->set(8,8,8);

    //Invoking display() member function using both obj4 and obj6 GameObjects
    cout << endl;
    cout << "Invoking display() member function using both obj4 and obj6 GameObjects " << endl;
    obj4.location->display();
    obj6.location->display();




    system("pause");
    return 0;
}

在这里,正如您在Main.cpp中看到的那样,只要obj4'位置'发生变化,obj6'位置'就会发生变化。当我更改obj4的位置时,我不想更改obj6'位置'。

执行此操作时出现此错误

GameObject.obj : error LNK2019: unresolved external symbol "public: __thiscall Location::Location(class Location const *)" (??0Location@@QAE@PBV0@@Z) referenced in function "public: __thiscall GameObject::GameObject(class GameObject const *)" (??0GameObject@@QAE@PBV0@@Z)

我尝试使用深层复制构造函数,但它不起作用。请帮忙。

5 个答案:

答案 0 :(得分:4)

GameObject::GameObject(const GameObject *ob)

不是复制构造函数,您需要:

GameObject::GameObject(const GameObject &ob)
                                       ^^^

此外,您需要提供执行深层复制的复制分配运算符

请注意,理想的解决方案是使用智能指针作为成员而不是原始指针 这基本上可以省去深度复制的所有麻烦。


好读:
What is The Rule of Three?

答案 1 :(得分:3)

tl; dr尝试实施复制构造函数而不是转换构造函数,即:

//this
GameObject(const GameObject &obj);
//instead of this
GameObject(const GameObject *obj);

答案 2 :(得分:2)

首先,正如其他人所指出的那样,你还没有实现一个复制构造函数。

GameObject::GameObject(const GameObject *ob)

这是一个带有指向const GameObject的指针的函数。复制构造函数应该对要从中创建的对象执行const引用:

GameObject::GameObject(const GameObject &ob)

但是,我也看到了另一个问题。如果您确实需要深层复制,这意味着您希望Location对象是独立的,并且修改一个对象不应该影响另一个。鉴于此,我认为没有理由为什么GameObject应该持有指向Location的指针,而不是一个简单的Location成员。因此,我建议更改此设置,并创建一个使用初始化列表的复制构造函数,使您的位置成为给定位置的副本:

将它放在GameObject标题中:

class GameObject
{
public: 
    GameObject(int);
    ~GameObject(void);
    GameObject(int,const Location&);
    GameObject(const GameObject &obj);

    Location location;

    int getNumberOfObjects();

    static int counter;


    int id;

private:
    GameObject(void);
}

编写像这样的构造函数:

GameObject(int i)
: id(i)
{}

// This will cause GameObject to be uninitialized
~GameObject(void)
{}

GameObject(int i,const Location& loc)
: id(i), location(loc)
{}

GameObject(const GameObject &obj)
: id(obj.id), location(obj.location)
{}

最后,您需要使用相同的逻辑来构造具有签名的正确的位置复制构造函数:

Location(const Location &loc);

我会把这个实现作为练习留给读者。 ;)

另外,阅读你的一些评论(比如一个实际上不是静态的成员上面的“静态”评论等)让我觉得你可能想要阅读更多关于C ++内存管理的内容。 :)谷歌在“C ++免费商店”上略有提升。提示不要在没有必要的地方使用动态内存。在C ++中,不是每个对象都应该使用new创建。

答案 3 :(得分:2)

在C ++中,可以在堆上创建对象,并将其内存地址存储在指针中。对象也可以在堆栈上创建,并可以通过引用指示。

定义我们的复制构造函数时,我们需要使用引用而不是指针。原因是在复制构造函数中使用指针会导致您有两个指向堆中同一对象的指针。所以你的"obj6""obj4"指针指向内存中的同一个对象。

答案 4 :(得分:1)

我发现你没有Location对象的copy contructor的实现。我想一旦你实现了方法Location(const Location * loc),问题就会得到解决。

Location(const Location* loc) {
   this->x = loc->x;
   this->y = loc->y;
   this->z = loc->z;
}