C++ copy object - c++

I have a class Game which contains an other object GameGrid:
Game.h
class Game
{
public:
Game(uint32_t GridSize);
private:
GameGrid _CurrentGrid;
}
Game.cpp
Game::Game(uint32_t GridSize) : _CurrentGrid(GridSize)
{
}
GameGrid.h
class GameGrid
{
public:
GameGrid(uint32_t GridSize);
void setGrid(const Grid& Grid);
const GameGrid::Grid getGrid(void) const;
private:
Grid _Grid;
}
GameGrid.cpp
GameGrid::GameGrid(uint32_t GridSize)
{
uint32_t i = 0;
uint32_t j = 0;
_Grid.assign(GridSize, std::vector<unsigned int>(GridSize));
for (i = 0; i < GridSize; i++)
{
for (j = 0; j < GridSize; j++)
{
_Grid.at(i).at(j) = 0;
}
}
}
void GameGrid::setGrid(const GameGrid::Grid& Grid)
{
_Grid = Grid;
}
const GameGrid::Grid GameGrid::getGrid(void) const
{
return _Grid;
}
Now I have my application, which uses the game class
Game* MyGame = new Game(4);
How can I create a copy function for this pointer to the Game-Object, so that I can clone the object.
I´ve tried it with the assignment operator
Game& operator=(Game const& Ref);
Game& Game::operator=(Game const& Ref)
{
if (&Ref != this)
{
this->~Game2048();
new (this) Game2048(Ref);
}
return *this;
}
But this solution doesn´t work and my original object got changed too, when I change the clone.
Does someone has a hint for me?
Thank you!

Don't create the copy constructor yourself and let the compiler do it for you, then just use objects:
Game MyGame{4};
Game gameClone = MyGame;
There's no reason to use a raw pointer here.

I agree to what #SombreroChicken hast said.
I just want to point out the difference between a deep copy and shallow copy.
If your class Contains some pointer as private member data, you have to be aware, that only the pointer is copied and not the data to which is being pointed. Here is a nice in depth explanation of what I said.

Related

Copy And Assignment: How to Deep Copy? C++

I have two classes that are essentially string classes that look like this.
The first class holds a string as a member and the second class also holds a string plus an array of pointers for the 'MenuItem' class and also a tracker.
const int MAX_NO_OF_ITEMS = 10;
class Menu; // forward declaration
class MenuItem {
char* Menuitem;
//member functions
MenuItem();
...
~MenuItem();
friend Menu;
};
class Menu {
private:
char* m_Title;
MenuItem* m_MenuItems[MAX_NO_OF_ITEMS];
int m_menuTracker;
... //other functions not shown
}
I want to be able to deep copy one Menu object to another Menu object but the way I am doing it seems do be as if it were a shallow copy when it comes to copying over the 'm_MenuItems'. I know for sure that the 'm_Title' member is getting deep copied as I am creating a 'new' char* for it but the problem arises when I am trying to copy the source 'm_MenuItems' to the destination as they end up sharing the same memory. This causes problems because when the deconstructor is called, it is called twice on the same object, causing my program to crash.
Here is my copy and assignment code:
Menu& Menu::operator=(const Menu& src) {
if (this != &src && src.m_Title != nullptr) {
delete[] m_Title;
m_Title = nullptr;
m_Title = new char[strlen(src.m_Title) + 1];
strcpy(m_Title, src.m_Title);
//if current object has menuItems, then delete to make room for src.
for (int i = 0; i < m_menuTracker; i++) {
delete m_MenuItems[i];
this->m_MenuItems[i] = nullptr;
}
This following for-loop is where my problem arises...
if (src.m_MenuItems[0] != nullptr) {
for (int i = 0; i < src.m_menuTracker; i++) {
m_MenuItems[i] = src.m_MenuItems[i];
}
this->m_menuTracker = src.m_menuTracker;
}
else
this->m_menuTracker = 0;
}
else {
this->setEmpty();
}
return *this;
}
How am I supposed to allocate a new block of memory for the destination 'm_MenuItems'?

Classes in C++ Constructor and D'tor

I have two Classes, Player and Game.
class Game
{
private:
int maxPlayer;
Player** playersArray;
public:
Game(int maxPlayer);
~Game();
}
Each index in playersArray consists of pointers to class Player.I'm not sure though how to make the constructor and destructor of the Class Game. This is my first try but the code isn't working any idea?
Game::Game(int maxPlayer)
{ this->playersArray = new Player*[maxPlayer];
for(int i=0;i<maxPlayer;i++)
{
playersArray[i]=NULL;
}
}
Game::~Game() {
for(int i=0;i<maxPlayer;i++)
{
delete[] *playersArray[i];
}
delete (playersArray);
}
It has been along time since I have programmed in C++. The only error I see for sure is that the constructor has a parameter maxPlayer and never touches the member variable maxPlayer. The destructor uses the member variable maxPlayer, which probably has never been initialized. The constructor ought to assign the parameter to the member variable.
When you delete an array you are supposed to use delete[] but you use delete for a single object. So, I think you have them swapped.
OK, since I did not get response to my comment, let me try this: If you modify your code as shown below, does it do what you expect it to do?
class Player
{
};
class Game
{
private:
int maxPlayer;
Player** playersArray;
public:
Game(int maxPlayer);
~Game();
};
Game::Game(int maxPlayer)
{
this->maxPlayer = maxPlayer;
this->playersArray = new Player*[maxPlayer];
for (int i = 0;i<maxPlayer;i++)
{
playersArray[i] = NULL;
}
}
Game::~Game() {
for (int i = 0;i<maxPlayer;i++)
{
delete playersArray[i];
}
delete[] playersArray;
}
int main()
{
Game g(10);
return 0;
}

How to make a copy function for a class with vector of pointers?

I have a class, Somec, with a vector of pointers to items. Each item in the vector is from another class type, Myitem.
I want to make a copy function for Somec, but I am having some problems.
Also, I have a copy function for Myitem, do I have to use it in the copy function for Somec?
What I have tried so far:
class Somec {
string Name;
std::vector<Myitem*> Items;
public:
Somec(const Somec& somec); // my copy function
};
/// this the clas to my item :
class Myitem {
Itemk itemk;
public:
// ... some fuction
};
// now I want to make a copy function for Somec
Somec::Somec(const Somec& somec) {
int size = somec.Items.size();
this->Items = new (vector*) (size); // i get an error here
this->Name = somec.Name;
for(int i = 0; i < size; i++) {
*Items.at(i) = *somec.Items.at(i);
}
}
UPDATE: I made the copy function just like Remy Lebeau told me to, but when I try to test this function the code stops working. This is how I am testing it:
class Somec {
string Name;
std::vector<Myitem*> Items;
public:
Somec(const Somec& somec); // my copy function
};
Somec::Somec(const Somec& somec) { // new copy function for somec
int size = somec.Items.size();
this->Name = somec.Name;
for(int i = 0; i < size; i++) {
Items.push_back(new Myitem(*somec.Items[i]));
}
}
// create item function
void Somec::createitem(char* name, const int& Time, const int& level) {
try{
Myitem* ORitem=new Myitem(name, Time, level);
Somec::Items.push_back(ORitem);
}
catch(MemoryProblemException& error) {
throw SomecMemoryProblemException();
}
}
std::vector<Myitem*> Somec::getAllItems() const {
return Items;
}
/// this the class to my item :
class Myitem {
Itemk itemk;
public:
// ... some fuction
};
// my copy function to MYitem
Myitem::Myitem(const Myitem& item){
Myitem* currie = Myitem::clone_item();
curritem->item = itemCopy(item.item);
if (!curritem->item) {
throw itemMemoryProblemException();
return;
}
}
void testCopy() {
Somec somec("name1")
somec.createitem((char*) "item1", 30, 1, 2);
Somec temp(somec);
int x=0;
if ( std::equal(somec.getAllItems().begin() + 1, somec.getAllItems().end(), somec.getAllItems().begin()) ) {
x++;
}
ASSERT_TRUE(x==1);
}
What is my problem? I mean, I did the copy function, I think it is true. But why does the code stop working? Am I testing this in the right way?
My createitem function, I am 100% sure about it, actually.
I am just trying to add items to the the vector in Somec and check if this happened correctly. I learned that in C++, we need a copy constructor, so I wrote one, and thought about testing it since this is my first time doing one.
If you want to copy elements from the vector of the other instance to the vector of your current instance in the copy constructor, then simply do this
class Somec {
string Name;
std::vector<Myitem> Items;
public:
Somec(const Somec& somec); // my copy function
};
i.e. make the vector of values instead of pointers.
If for some reason you have to have to work with pointers, because maybe the copy constructor is deleted or something similar. Then still use this approach, but just don't copy the contents of in the copy constructor, let them get constructed and then assign them
Somec(const Somec& somec) {
this->Items.resize(somec.Items.resize());
for (std::size_t i = 0; i < somec.Items.size(); ++i) {
this->Items[i] = somec.Items[i];
}
// or simply
this->Items = somec.Items;
}
The default compiler-generated copy constructor already does exactly what your copy constructor is doing manually. So it is redundant code.
However, assuming Somec owns the items, then you do need to define a custom copy constructor, and it needs to allocate new Myitem objects and copy the existing data into them, eg:
Somec::Somec(const Somec& somec) {
this->Name = somec.Name;
std::size_t size = somec.Items.size();
this->Items.reserve(size);
for(std::size_t i = 0; i < size; i++) {
Items.push_back(new Myitem(*somec.Items[i]));
}
}
You will have to do something similar in an overriden operator= as well. You can utilize the copy constructor to help you:
Somec& Somec::operator=(const Somec& somec) {
if (&somec != this) {
Somec temp(somec);
std::swap(this->Name, temp.Name);
std::swap(this->Items, temp.Items);
}
return *this;
}
And, of course, make sure you free the owned items in the destructor:
Somec::~Somec() {
std::size_t size = somec.Items.size();
for(std::size_t i = 0; i < size; i++) {
delete Items[i];
}
}
See Rule of Three for more details about why this trio is needed.

invalid use of non-static data member 'Board::N'

This is the header:
class Board {
public:
friend class Game;
Board() = default;
Board(int n) : N(n) { }
Board& SetType(int, int, char);
void GetType(int, int);
Board& CreateEmptyBoard();
void BoardDisplay();
private:
int N = 0;// dimension
char Maze[15][15];
const static int MaxSize = 15;
};
class Game {
public:
Game() = default;
Game(int x, int y) : PosX(x), PosY(y) { }
void BuildGame();
void GameDisplay();
void MoveUp();
void MoveDown();
void MoveLeft();
void MoveRight();
private:
int PosX = 0;
int PosY = 0;
};
void Game::BuildGame() {
srand(time(NULL));
for (int i = 0; i < Board::N; i++) {
for (int j = 0; j < Board::N; j++) {
if (i == rand() % (Board::N) && j == rand() % (Board::N))
Board::Board& SetType(i, j, 'W');
}
}
}
In class Game's member function void BuildGame,I want to call member functionBoard& SetType(int,int,char) in class Board.I define this function in a header file and not show here. Then I build the project, I got invalid use of non-static data member 'Board::N' and 'SetType' was not declared in this scope. Like this
Where I wrong? I can't find it.
The compiler is letting you know that you are using an instance variable as a static. A static variable is associated with an entire class and not a single object, so it is called through the class name and not an object of the class. but it would need to be marked as static like so
class Board
{
public:
static Board& setType(int, int, char);
...
private:
static int N;
...
}
my instinct however tells me that you want to use it at an instance level, so you would write your void Game::buildGame() method using a Board that it creates (possibly making it an attribute of the Game class:
void Game::BuildGame() {
//make your board here. alternatively make an instance of the game
Board myBoard();
srand(time(NULL));
//in the following, use myBoard as the instance of a board.
for (int i = 0; i < myBoard.N; i++) {
for (int j = 0; j < myBoard.N; j++) {
if (i == rand() % (myBoard.N) && j == rand() % (Board::N))
myBoard.setType(i, j, 'W');
}
}
}
And a Board class that looks something like this. You will probably want your setType method to modify the instance and return void instead of returning another board reference.
class Board
{
public:
//this one will change this particular Board instance.
void setType(int, int, char);
//this one may make sense to be static if it is a factory method
//but why not use a constructor instead?
static Board& createEmptyBoard();
//maybe you meant something to reset the board to empty state.
void resetBoardToEmpty();
...
private:
int N;
...
}
while you're at it you might make it a struct (which has members public by default) as it seems to be a "hidden" holder class for the game, and this would alleviate the need to use a friend class (these are to be used judiciously as they can get messy really fast). using a struct would also allow you to make a ChessGame class that reuses the Board struct.
N isn't a static member of class Board, hence you'll need an instance of board to access it.
Your Game class actually needs to have a Board member variable to achieve that above mentioned instance.

Some data lost while passing std::vector as in/out reference parameter

I'm having trouble transferring some data contained in a vector between my functions. The situation is as follows:
void generateObjects(std::vector<MyClass> &objects)
{
objects.clear();
//Fill objects vector
std::vector<MyClass> p;
//This 4-line pattern is repeated a number of times to generate all objects and store them in variable 'objects'
p.clear();
generateSomeOfTheObjects(p); //p is again passed by ref. in/out parameter
for(uint j = 0; j < p.size(); p++){
objects.push_back(p[j]);
}
//Print some members of the objects - works fine
for(uint i = 0; i < objects.size(); i++){
printf("%f ",objects[i].mymember->myElm);
}
}
int main()
{
std::vector<MyClass> objects;
generateObjects(objects);
//Print size of vector - size is correct it is the same as it is in generateObjects func
printf("%lu\n",objects.size());
//Again print members of the objects - some members are retained after the function call, some are lost.
//The one below doesn't work, mymember is a pointer to another object and its member myElm seems not initialized.
for(uint i = 0; i < objects.size(); i++){
printf("%f ",objects[i].mymember->myElm);
}
//Here I need to pass the objects to another read-only function
...
}
I have searched the internet for similar cases and actually found many, but I couldn't apply the same fixes to my code. I'm trying to reach a member of an object pointed to by a member of a MyClass instance (objects[i].mymember->myElm) What possibly am I missing here?
Probably the error lies in the implementation of MyClass. I'd say that this class contains some pointer that is initialized with the address of a local variable, so when you return from some of the functions that pointer points to a destroyed object.
That would undefined behavior but it may work by chance. When you return from the first function, the stack memory is finally overwritten and your data is lost.
UPDATE: Thanks to the insight by #chris in the comments below, the most likely reason is that your MyClass does not have a copy constructor, but it does have a pointer member.
Something like this:
class MyClass
{
public:
Member *mymember;
MyClass()
{
mymember = new Member;
}
~MyClass()
{
delete mymember;
}
};
Now what happens if you use the compiler generated default copy constructor (or the copy operator)?
void foo()
{
MyClass a;
{
MyClass b(a);
}
//a.mymember is no longer valid
}
Both a and b share the same pointer mymember, so when one of them is destroyed, the mymember is deleted and the other one holds a dangling pointer.
That's why we have the rule of three. It states:
Whenever you define a non-default destructor, you most likely will want also a non-default copy-constructor and a non-default copy-operator.
Now you have to decide if you want to share the ownership of the mymember or if you want to copy it. The first one is best done with smart pointers (shared_ptr) and the second one with deep copy.
For example, deep copy:
class MyClass
{
public:
Member *mymember;
MyClass()
{
mymember = new Member;
}
MyClass(const MyClass &c)
{
mymember = new Member(c.mymember);
}
MyClass &operator=(const MyClass &c)
{
if (this != &c) //be aware of self-copy
{
delete mymember;
mymember = new Member(c.mymember);
}
return *this;
}
~MyClass()
{
delete mymember;
}
};
And with shared pointers:
class MyClass
{
public:
std::shared_ptr<Member> mymember; //or boost::shared_ptr if old compiler
MyClass()
:mymember(new Member)
{
}
//no custom-made destructor -> no rule of 3
};
Perhaps unrelated to you question, but this:
void generateObjects(std::vector<MyClass> &objects)
{
objects.clear();
std::vector<MyClass> p;
p.clear();
generateSomeOfTheObjects(p);
for(uint j = 0; j < p.size(); p++){
objects.push_back(p[j]);
}
for(uint i = 0; i < objects.size(); i++){
printf("%f ",objects[i].mymember->myElm);
}
}
Is the same as this:
void generateObjects(std::vector<MyClass> &objects)
{
objects.clear();
generateSomeOfTheObjects(objects);
std::reverse(objects.begin(), objects.end());
for(uint i = 0; i < objects.size(); i++) {
printf("%f ",objects[i].mymember->myElm);
}
}
You copy issues, as #rodrigo mentioned, is that you are not doing deep copies with your copy constructors.