Home > front end >  Vector of subclasses
Vector of subclasses

Time:12-10

I need to do 4 classes. Superclass robot, two subclasses r1 and r2 and class line. Classes robot, r1 and r2 has one static member l_obiektow which are used to display number of objects and two virtual methods praca which is used to display type of an object and clone which is used to make copy of an object. Class line is used to manage vector of objects r1 and r2. I have a problem with method clone, I'm not sure what type should i return and what should it do.

#include <vector>
using namespace std;
class robot;
//typedef  robot* wsk;
using wsk = robot*;

class robot{
  protected:
  static int l_ob;
  public:
  static int l_obiektow(){return l_ob;}
  virtual ~robot(){ cout << "~robot()" << endl;}
  virtual void praca()const=0;
  virtual wsk clone()const=0;
};

class r1 : public robot {
  public:
  r1(){l_ob  ;}
  r1(const r1& r){l_ob  ;}
  void praca()const{
        cout<<"r1"<<endl;
  }
  virtual wsk clone()const{
        r1 tmp=r1(*this);
        return &tmp;
  }
  ~r1(){cout << "~r1()" << endl; l_ob--;}
};

class r2 : public robot {
    public:
  r2(){l_ob  ;}
  r2(const r2& r){l_ob  ;}
  void praca()const{
        cout<<"r2"<<endl;
  }
 virtual wsk clone()const{
        r2 tmp=r2(*this);
        return &tmp;
  }
  ~r2(){cout << "~r2()" << endl; l_ob--;}
};

class line{
  vector <wsk> ve;

  public:
  line(){}
  line(int r):ve(r){
    for(size_t i=0; i<ve.size();   i )
      cout << ve[i] << ", " ;
    cout << endl;
  }

  line(const wsk* b, const wsk* e){
        size_t roz=e-b;
        for(size_t i=0;i<roz;i  ){
            ve.push_back(b[i]->clone());
        }
    }
  line(const line& arg){
        for(size_t i=0;i<arg.ve.size();i  ){
            ve.push_back(arg.ve[i]->clone());
        }
  }
  line& operator = (const line& a){
        if(this!=&a){
            ve.clear();
            for(size_t i=0;i<a.ve.size();i  ){
                ve.push_back(a.ve[i]->clone());
            }
        }
        return *this;
  }

  void add( const wsk& arg){
    ve.push_back(arg);
  }
  void del(int i){
    delete ve[i-1];
    ve.erase(ve.begin() i-1);
  }
  void delet(){
    delete ve[ve.size()-1];
    ve.pop_back();
  }

  void work(){
     for(size_t i=0;i<ve.size();i  ){
        ve[i]->praca();
     }
  }
  ~line(){
        for(size_t i=0;i<ve.size();i  ){
            delete ve[i];
        }
        ve.clear();
        cout<<"~line()"<<endl;
  }

};

int robot::l_ob=0;
void numberofobj(){
  cout << robot::l_obiektow() << endl;
}
int main()
{
    {
    { line l1 ;    }
    { line l2(5) ; }
    cout << "--==**1**==--" << endl;
    line lp1, lp2;
    lp1.add(new r1);
    lp1.add(new r1);
    lp1.add(new r2);
    lp1.add(new r2);
    lp2=lp1;
    {
      line lp3;
      lp3.add(new r1);
      lp3.add(new r2);
      lp3.add(new r1);
      lp3.add(new r2);
      lp3.delet();
      cout << "--==**2**==--" << endl;
      lp3.work();
      lp1 = lp3;
      cout << "--==**2a**==--" << endl;
    }

    cout << "--==**3**==--" << endl;
    lp1.work();
    cout << "--==**4**==--" << endl;

    wsk TabAdrRob[] = {new r2, new r2};
    line lp4(TabAdrRob, TabAdrRob 2 );
    lp4.work();
    cout << "--==**5**==--" << endl;
    lp4 = lp2;
    lp4.work();
    cout << "--==**6**==--" << endl;
    line lp6(lp1);
    lp6.del(1);
    lp6.work();
    cout << "--==**7**==--" << endl;

    delete TabAdrRob[0];
    delete TabAdrRob[1];}

  numberofobj();
  return 0;
}

CodePudding user response:

This is a serious bug:

virtual wsk clone()const{
        r1 tmp=r1(*this);
        return &tmp;      // returning pointer to a local object
  }

You are returning a pointer to a local object on stack. After clone() returns, tmp will be destroyed.

Dont use raw owning pointers. Use smart pointers instead, ex. unique_ptr .

It's also a good habit to use override in subclasses, so the compiler can emit an error if you override the wrong method. You don't need virtual in subclasses, if subclasses are not meant to be derived from (it's an old way of marking virtual methods in a pre C -11 era).

So the method becomes:

unique_ptr<robot> clone() const override
{
   return make_unique<robot>(new r1(*this));
}

And for the list of robots you could use a vector of smart pointers vector<unique_ptr<robot>>, so that all objects vector are automaticaly destroyed and memory freed.

  • Related