Home > database >  Deep copying a vector of pointers in derived class
Deep copying a vector of pointers in derived class

Time:04-17

I have a pure virtual class called Cipher

class Cipher
{
public:
    //This class doesn't have any data elements
    virtual Cipher* clone() const = 0;
    virtual ~Cipher() { };
    //The class has other functions as well, but they are not relevant to the question
};

Cipher has a few other derived classes (for example CaesarCipher). The question will be about CipherQueue, which looks something like this:

//I've tried to only include the relevant parts here as well
class CipherQueue: public Cipher
{
    std::vector<Cipher*> tarolo;
public:
    void add(Cipher* cipher)
    {tarolo.push_back(cipher);}
    
    CipherQueue(const CipherQueue& _rhs); //?????
    CipherQueue* clone() const;           //?????


    ~CipherQueue()
    {
        for (size_t i = 0; i < tarolo.size(); i  )
        {
            delete tarolo[i];
        }
        //tarolo.clear(); //not sure if this is needed
    }

CipherQueue has a vector called tarolo. It contains pointers to the derived classes of Cipher. You can add elements to this vector by using the new operator, or the clone function (which has already been implemented) of the given class:

CipherQueue example;
example.add(new CaesarCipher(3))
CaesarCipher c(6);
example.add(c.clone());
//It is the job of the CipherQueue class to free up the memory afterwards in both cases

Now the question is: how can I implement the copy constructor and the clone function in CipherQueue, so that the copy constructor is used in the clone function, and the clone function creates a deep copy of the object that it is called on? I've already made what I think is a shallow copy, which isn't good, because the destructor, ~CipherQueue() doesn't work with a shallow copy. (Or could the destructor be wrong as well?) The goal is to make it so that you can do something like this:

CipherQueue example;
CipherQueue inside; //Let's say that this already has a few elements in it
example.add(inside.clone());
example.add(example.clone()); //This should also work

Here's what I've tried before, without using the copy constructor (which is a shallow copy I think, and therefore it causes my program to get a segmentation fault):

    CipherQueue* clone() const
    {  
        CipherQueue* to_clone = new CipherQueue;
        to_clone->tarolo = this->tarolo;
        return to_clone;
    }

CodePudding user response:

Thank you Marius Bancila, you are right, the problem was that I was just copying the pointers, and not creating new objects in the new vector. I called clone() on each object, and now it works perfectly! Here is the working clone function, in case anyone stumbles upon this thread in the future:

    CipherQueue* clone() const
    {
        CipherQueue* to_clone = new CipherQueue;
        to_clone->tarolo = this->tarolo; //First we copy the pointers
        for (size_t i = 0; i < this->tarolo.size(); i  )
        {
            to_clone->tarolo[i] = tarolo[i]->clone(); //Then we use the clone function on each element to actually create new objects, and not just have copied pointers
        }
        return to_clone;
    }

In the end, it seems like I didn't need the copy constructor at all. You can make the clone function without it.

  • Related