Read the Solution
Read the Conclusion
The Problem
Recently I came across a problem when copying vectors in c++. So I say something like this:clone_vector = original_vector;
Where the orignal_vector is a vector of pointers to objects, all of which have a common base class and also a string stream as a private member. A simplified version of the objects held in the vector is as follows:
class Digit
{
protected:
//x and y positons
int Xpos;
int Ypos;
//value in string format
std::stringstream svalue;
public:
Digit();
};
class Realnum: public Digit
{
protected:
float value;
public:
Realnum( int x, int y);
};
The problem with the copy statement is that this is what is called "shallow copying". Shallow copying does not dereference pointers, in other words pointers in the clone_vector point to the address of pointers in the original_vector. So if you change a value in the orignal_vector you will automatically change a value in the clone_vector and vice versa. A good picture and explanation of deep vs shallow copy can be found at the wikipedia page . I want to be able to create a clone copy of my vector that I can manipulate without manipulating the original and vice versa.
Solution
To deep copy a vector composed of objects in a derived class that also contain a string stream member (trust me that's imposing a lot of conditions, if you can copy this you can copy anything) you need to do the following.
1. Create a copy constructor such that each time an object is created in the clone vector it has it is deferenced
(a copy constructor is a constructor that takes a previously existing instance and make a copy of it. Read about it here)
2. create a desctructor
3. create a clone function to properly create a copy
4. Implement a copying process to create clones of vectors
So Here is what The class now looks like:
class Digit { protected: //x and y positons int Xpos; int Ypos; //value in string format std::stringstream svalue; public: Digit(); Digit(const Digit ©) { Xpos = copy.Xpos; Ypos = copy.Ypos; svalue << copy.svalue.str(); } ~Digit(); //copy fucntion virtual Digit* clone() const { return new Digit( *this ); } }; class Realnum: public Digit { protected: float value; public: Realnum( int x, int y); Realnum(const Realnum ©): Digit(copy) { value = copy.value; } ~Realnum(); //copy fucntion Realnum* clone() const {return new Realnum( *this);} };Notice that the derived class has a copy constructor which gives argument to the super classes copy constructor and that each copy constructor assigns every private member (variables of the object) a value. That what needs to be done if you want to use polymorphism when copying. Also notice that the clone function is virtual in the base class. That is because it is better to define a clone function for each subclass. Now copy using this technique:
//resize the clone vector
clone_vector.resize(original_vector.size());
for(int i=0; i< original_vector.size(); i++)
{
clone_vector[i] = original_vector[i]->clone();
}
each element of the vector is properly cloned using deep copy.
Voila!
An object copy is a process where a data object has its attributes copied to another object of the same data type. In .Net Shallow copy and deep copy are used for copying data between objects....more.
ReplyDelete