1

请看下面的代码

位置.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;
};

位置.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;
}

对象.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);



};

对象.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)
{
}

主文件

#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 中看到的,obj6 'Location' 已在 obj4 'Location' 更改后立即更改。当我更改 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)

我试图用一个深拷贝构造函数来做,但它没有用。请帮忙。

4

5 回答 5

4
GameObject::GameObject(const GameObject *ob)

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

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

此外,您需要提供一个复制赋值运算符来执行深层复制。

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


好读:
什么是三法则?

于 2012-12-06T05:57:02.553 回答
3

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

//this
GameObject(const GameObject &obj);
//instead of this
GameObject(const GameObject *obj);
于 2012-12-06T05:56:18.457 回答
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 复制构造函数:

Location(const Location &loc);

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

此外,阅读您的一些评论(例如实际上不是静态的成员上方的“静态”评论等)让我认为您可能想阅读更多关于 C++ 内存管理的内容。:) 谷歌一下“C++ 免费商店”。一个提示是不要在不需要的地方使用动态内存。在 C++ 中,并非每个对象都应该使用new.

于 2012-12-06T06:40:10.437 回答
2

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

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

于 2012-12-06T06:56:24.957 回答
1

我看到您没有 Location 对象的复制构造函数的实现。我想一旦你实现方法 Location(const Location* loc),问题就会得到解决。

Location(const Location* loc) {
   this->x = loc->x;
   this->y = loc->y;
   this->z = loc->z;
}
于 2012-12-06T06:32:32.103 回答