Reputation: 655
I have a class B which has a member that is a pointer to an object of a A class. When using copy constructor on an object of type A, it is copied but the member variable is not. Is there any way to copy an A object and to automatically make a copy of its B member? The following code shows the problem I'm triying to explain:
class A
{
public:
A(char t_name)
{
name = t_name;
}
~A()
{
}
char name;
};
class B
{
public:
A* attribute;
B()
{
attribute = new A('1');
}
~B()
{}
};
int main()
{
B* b_variable = new B;
B* b_copy = new B(*b_variable);
return 0;
}
Upvotes: 1
Views: 398
Reputation: 44274
When using copy constructor on an object of type A, it is copied but the member variable is not.
Your code never calls any copy constructor in class A.
Your code calls a copy constructor in class B and it does exactly what is is supposed to, i.e. copies the value of attribute
which is a pointer to a class A object.
In other words - after executing your code, you have two instances of class B and one class A instance. In the two class B instances attribute
points to the same class A instance.
This is (most likely) not what you want.
As many already has pointed out (e.g. see @lostbard answer), you'll need a copy constructor in class B to do a deep-copy. A deep-copy is needed because class B have a pointer member.
Also you should do some clean up in class B destructor and in main.
#include <iostream>
using namespace std;
class A
{
public:
A(char t_name)
{
name = t_name;
}
~A()
{
}
char name;
};
class B
{
public:
A* attribute;
B()
{
attribute = new A('1');
}
/** Copy constructor */
B(const B ©)
{
// Make a new instance of class A
attribute = new A(*copy.attribute);
}
/** Assignment operator */
B& operator= (const B& other)
{
// Delete the existing class A instance
delete attribute;
// and create a new as a copy of other.attribute
attribute = new A(*other.attribute);
}
~B()
{
// Delete the class A instance
delete attribute;
}
};
int main()
{
B* b_variable = new B;
B* b_copy = new B(*b_variable);
// Delete the two class B instances
delete b_variable;
delete b_copy;
return 0;
}
There is no need for a copy constructor in class A. The default generated will do as Class A has no pointer members.
EDIT
As pointed out by @Slava you should always implement a assignment operator when you make a copy constructor (rule of three) so I added it to the code above.
Some like the rule of three to be the rule of five so it also include move. Read more here: https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)
Upvotes: 1
Reputation: 5220
Create a copy constructor for A and for B:
class A
{
public:
A(char t_name)
{
name = t_name;
}
A(const A& copy)
{
name = copy.name;
}
~A()
{
}
char name;
};
class B
{
public:
A* attribute;
B()
{
attribute = new A('1');
}
B(const B ©)
{
attribute = new A(*copy.attribute);
}
~B()
{}
};
Upvotes: 0
Reputation: 10880
While there are many solutions, I'd bet sooner-or-later you'll end up with implementing the usual virtual a.clone();
. That works flawless when you'll have derived classes of A (which is more-or-less the only legitimate reason why you're keeping A as a pointer to a heap-allocated object and not as a value member :) ).
Note that, when you're implementing clone()
in your hierarchy, that C++ supports covariant pointer return types. Thus, if base has a virtual that returns e.g. Clonable*
, then A
's same method can return A*
and A's descendant ADerived
can return ADerived*
. Feel free to understand 'can' as 'should' for the case of clone()
.
Upvotes: 0