1

I'm stock on this problem and all the solutions that I found here doesn't work for me.

First, I have this class:

class Flow {
public:
    Flow();
    ...
    virtual double execute() = 0;
    ...
private:
    ...
};

That's working fine in my subclass tests. And I also have this Class:

class Model {
public:
    Model();
    ...
    Model(const Model& mdl);
    Model& operator=(const Model& mdl);
    ...
private:
    string name;
    vector<Flow*> flows;
    ...
};

And in the copy constructor, i have to copy the Flow* vector to another Flow* vector, and I'm doing this:

Model& Model::operator =(const Model& mdl) {
    this->name = mdl.name;
    this->flows.resize(mdl.flows.size());
    for (unsigned int i = 0; i < mdl.flows.size(); i++) {
        *this->flows[i] = *mdl.flows[i];
    }
    return *this;
}

But isn't working. I can't initialize a empty Flow object at this point, because the execute() method is pure virtual;

I tried to use transform(), but the clone() method needs to implement the Flow();

What I'm doing wrong?

UPDATE: This way works:

Model& Model::operator =(const Model& mdl) {
    this->name = mdl.name;

    for (unsigned int i = 0; i < mdl.flows.size(); i++) {
        Flow *cp = (Flow*) malloc(sizeof(mdl.flows[i]));
        this->flows.push_back(cp);
    }

    return *this;
}
Dk Ribeiro
  • 113
  • 8
  • You have not defined the ownership. You may use `std::shared_ptr` and share the polymorph objects (Note: you deep copy is totally wrong - it copies into random memory (uninitialized pointer)) –  Feb 24 '16 at 17:27
  • "I can't initialize a empty Flow object at this point, because the execute() method is pure virtual". If it weren't pure virtual, an empty Flow object wouldn't do you any good anyway. Do you understand why? – n. m. could be an AI Feb 24 '16 at 17:31
  • @n-m Yes, I was just preventing this suggestion – Dk Ribeiro Feb 24 '16 at 17:36
  • @DieterLücking But I can't initialize the Flow object to use shared_ptr – Dk Ribeiro Feb 24 '16 at 17:42
  • 2
    @DkRibeiro What is the reason why `Model` needs to be copyable? If it doesn't make sense for `Model` to be copied, disable it. You really need to determine *"what does it mean to make a copy of a Model?" It isn't just about blindly copying a container of Flow pointers and some member variables -- you have to make a choice based on design and real-case uses. Sometimes classes just aren't made to be copyable -- a good example are stream classes. – PaulMcKenzie Feb 24 '16 at 18:03
  • @PaulMcKenzie Actually this doesn't have any utility, but it's required by my teacher on this assignment. – Dk Ribeiro Feb 24 '16 at 18:09
  • 2
    @DkRibeiro Well, your teacher needs to answer the questions I asked. What does it mean to "copy a Model"? Not just a syntax-based answer, but a conceptual answer. Does it mean that each Model shares the pointers that are in the Flow vectors? Does it mean that each Model has totally distinct Flow objects in a vector? Again, there are scenarios where copying an object makes very little sense, I give you the C++ `stream` classes. You cannot copy stream classes, because copying is turned off. Why? Because it made no conceptual sense to copy a stream object. – PaulMcKenzie Feb 24 '16 at 18:15

4 Answers4

2

One of the solutions is to add pure virtual method clone and implement it in each derived class:

class Flow {
public:
    ...
    Flow *clone() const = 0;
};

class Foobar : public Flow {
public:
    ...
    Flow *clone() const { return new Foobar(*this); }
};

and your loop will be this:

for (unsigned int i = 0; i < mdl.flows.size(); i++) {
    this->flows[i] = mdl.flows[i]->clone();

you should consider using smart pointers for proper memory control though.

If you cannot add a virtual method then you cannot deep copy your objects, so you either need to change your ownership to shared (through std::shared_ptr) or prohibit copying Model objects (if you use c++11 you may allow move assignmennt though)

Note: even if you make your current statement compile, making your virtual method not pure, it will not work as you expect it because of What is object slicing?

Community
  • 1
  • 1
Slava
  • 43,454
  • 1
  • 47
  • 90
1

You can only make a item copy at this way, if you can initialize the object. I'm having the same issue!

0

After try many things, I finally came to this solution, that's works:

Model& Model::operator =(const Model& mdl) {
    this->name = mdl.name;

    for (unsigned int i = 0; i < mdl.flows.size(); i++) {
        Flow *cp = (Flow*) malloc(sizeof(mdl.flows[i]));
        this->flows.push_back(cp);
    }

    return *this;
}
Dk Ribeiro
  • 113
  • 8
0

Your code is almost correct, but you need to copy the content to the new pointer

Model& Model::operator =(const Model& mdl) {
    this->name = mdl.name;

    for (unsigned int i = 0; i < mdl.flows.size(); i++) {
        Flow *cp = (Flow*) malloc(sizeof(mdl.flows[i]));
        *cp = * mdl.flows[i]; //The content is copied here
        this->flows.push_back(cp);
    }

return *this;
}

you can also use interator like this:

Model& Model::operator =(const Model& mdl) {
    this->name = mdl.name;

    vector<Flow*>::iterator it;
    for(*it = mdl.flowBegin() ; *it!=mdl.flowEnd(); it++){
        Flow *cp = (Flow*) malloc (sizeof(it));
        *cp=**it; //The content is copied here
        Flows.push_back(cp);
    }

return *this;
}   

but in this case you need to create a method in your class Flow that return a pointer to the beggin and the end of the vector.