Reputation: 150
So I am quite confused about copy constructors in C++. I have the following code:
class creature /* abstract class*/
{
private:
string name;
int longevity;
creature_society * cs;
public:
creature(int,int,int,creature_society*);
//creature(const creature&);
virtual ~creature();
virtual int is_a_good() =0;
};
class good_creature : public creature
{
public:
good_creature(int,int,creature_society*);
//good_creature(const good_creature&);
~good_creature();
int is_a_good() //returns 1
};
class bad_creature : public creature
{
public:
bad_creature(int,int,creature_society*);
//bad_creature(const bad_creature&);
~bad_creature();
int is_a_good(void); //returns 0
}
So I have an abstract class called creature
, a good_creature
and a bad_creature
which are a children class of creature
.
At my program I also have an array called society
which has type of creature*
objects. If my creature through a condition is defined as good, I allocate space for it and store it in society
array as good_creature
. The same happens for bad creature. I construct it as described in the following code:
society = new creature*[M];
for(i=0;i<M;i++)
{
if(condition)
society[i] = new good_creature(L,good,this);
else
society[i] = new bad_creature(L,bad,this);
}
So I have to make a pure virtual function: creature::clone(int position)
which if it's either a good_creature
or a bad_creature
, it has to delete the society[pos]
and make a copy of the society[pos-1]
through a copy constructor.
So for example my good_creature::clone(int position)
is like this:
void good_creature::clone(int position)
{
int cop_pos=position -1; //getting the position before that in order to copy it
delete society[pos];
society[pos] = new good_creature( *society[cop_pos] );
//....
}
I get an error because society[cop_pos]
is of type creature*
. I tried casting it to good creature but unfortunately I keep getting errors. Is it because I am not calling the copy constructor right, is it because I am not casting right? Any ideas? This has been buffling me for 2 days. Keep in mind I' m a newbie and might have done something wrong.
Also I don't need to define my own copy constructor since all the elements in society[i]
point at the same object that is defined by creature_society * cs
, so I'm trying to use the default constructors since I do not need deep copy.
Thanks for your time.
UPDATE
A class I forgot to mention and the way I construct society
class creature_society
{
private:
int N; // number of the creatures we want to be made in society
creature ** society;
public:
creature_society(int,int);
~creature_society();
};
Upvotes: 0
Views: 368
Reputation: 4010
Use polymorphism and virtual dispatch to do the work for you.
Define a clone virtual function in creature class.
class creature
{
virtual creature * clone() = 0;
}
and then override it in children:
class good_creature: public creature
{
virtual creature * clone() override
{
return new good_creature(*this);
}
}
and similar for bad_creature.
Then use it:
society[pos] = society[pos - 1]->clone();
Side note: your design seems to influenced by languages like Java. This is not a (modern) C++-style. For example, in modern C++ ownership is better expressed by unique_ptr
instead of pointers. This would make code cleaner and much safer.
Upvotes: 3
Reputation: 7324
You don't know if society[cop_pos]
is the correct type, so you cannot safely cast. A better solution is to use a virtual function to create a copy
class creature {
public:
virtual creature* clone() const = 0;
...
};
class good_creature {
public:
good_creature* clone() { return new good_creature(*this); }
...
};
//Similar for bad_creature (and any other derived classes)
In your case you'd call it like this:
society[pos] = society[cur_pos]->clone();
There's no need to know the type of the object you're cloning. The virtual function call takes care of that for you. Note that good_creature::clone
returns a good_creature*
instead of a creature*
. This is a valid overload. A virtual function overload is allowed to return a derived class. In this case you could have it return a creature*
as well.
Upvotes: 4
Reputation: 313
The problem is that society
is an array of creature
, not of good creature
, so the copy constructor doesn't apply.
You can define a constructor for good_creature
and for bad_creature
taking as argument a creature:
good_creature(const creature&);
Upvotes: 1