簡體   English   中英

Deep Copy構造函數中的問題

[英]Issue in Deep Copy Constructor

請看下面的代碼

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

對象

#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'Location'被更改,obj6'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)

我嘗試使用深度復制構造函數來執行此操作,但此操作無效。 請幫忙。

GameObject::GameObject(const GameObject *ob)

不是副本構造函數,您需要:

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

另外,您需要提供執行深層復制的副本分配運算符

請注意,理想的解決方案是使用智能指針作為成員,而不是原始指針。
基本上,這將為您節省所有深層復制的麻煩。


讀得好:
什么是三法則?

tl; dr嘗試實現復制構造函數而不是轉換cnstructor ,即:

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

首先,正如其他人指出的那樣,您尚未實現復制構造函數。

GameObject::GameObject(const GameObject *ob)

這個函數需要一個指向const GameObject的指針。 復制構造函數應采用const引用,該引用將由以下對象創建:

GameObject::GameObject(const GameObject &ob)

但是,我也看到另一個問題。 如果您確實確實想要深層副本,則意味着您希望Location對象是分離的,並且修改其中一個對象不應影響另一個對象。 鑒於此,我認為沒有理由為什么GameObject應該持有指向Location的指針,而不是簡單的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 ++中內存管理的更多信息。 :) Google在“ C ++免費商店”上有點了。 提示是不要在不需要的地方使用動態內存。 在C ++中,並非每個對象都應使用new創建。

在C ++中,可以在堆上創建對象,並將它們的內存地址存儲在指針中。 也可以在堆棧上創建對象,並可以通過引用來指示。

在定義復制構造函數時,我們需要使用引用而不是指針。 原因是在復制構造函數中使用指針會導致您擁有兩個指向堆中同一對象的指針。 因此,您的"obj6""obj4"指針指向內存中的同一對象。

我看到您沒有Location對象的復制構造器的實現。 我想這個問題將在您實現方法Location(const Location * loc)后得到解決。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM