tiempo
tiempo

Reputation: 150

Copy constructor call C++

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

Answers (3)

Ilya Popov
Ilya Popov

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

Kevin
Kevin

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

Luca Pizzamiglio
Luca Pizzamiglio

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

Related Questions