-2

I have a code where there are some pointers to derived classes of the same base class. At one point I need to create another pointer to one of this derived classes, but I don't know at compile time to which class it will point to. Here an example of the code:

#include <iostream>
using namespace std;

class Polygon {
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b; };
    virtual int area() = 0;
};

class Rectangle: public Polygon {
  public:
    int area()
      { return width*height; }
};

class Triangle: public Polygon {
  public:
    int area()
      { return width*height/2; }
};

int main () {
  Rectangle* rect = new Rectangle;
  Triangle* trgl = new Triangle;
  Polygon* ppoly;
  trgl->set_values (4,5);
  ppoly = trgl;
  cout << ppoly->area() << '\n';
  trgl->set_values (8,5);
  cout << ppoly->area() << '\n';
  return 0;
}

Writing the code as above, 'ppoly' points to the same memory as trgl, so the 2 lines cout << ppoly->area() << '\n' print different results because I have changed width of the pointer trgl. In my codeI don't want this behaviour, but I would like that ppoly is a new pointer of the same type of trgl. I have tried to use Polygon* ppoly = new Polygon, but returns me an error at compile time:

error: invalid new-expression of abstract class type 'Polygon'

How can I correct the software?

Mattia
  • 135
  • 3
  • 13

2 Answers2

3

What you are asking for is virtual (copy) constructor i.e. a clone() function.

dimm
  • 1,792
  • 11
  • 15
1

Obviously, you can't instantiate a derived class using nothing but base-class-related constructs. But a base-class pointer still has a derived-class instance behind it, and it can encapsulate the "ability" to construct another instance.

This idiom is known as a Virtual Constructor - and it is not even difficult to implement. In a nutshell, you'll have a non-static virtual method which constructs a new instance on the heap, and is usable from the base class. It will look something like:

Polygon* poly = get_a_poly_which_really_is_some_derived_class();
Polygon* another_poly = poly->create();

Notes:

einpoklum
  • 118,144
  • 57
  • 340
  • 684