1

I have the next code

class Shape 
{
public:
    virtual Shape* create()     { return new Shape; }
    virtual void print()        { cout << "Shape" << endl; }
    virtual ~Shape()            {}
};

class Circle : public Shape 
{
public:
    virtual Circle* create()        { return new Circle; }
    virtual void print()            { cout << "Circle" << endl; }
};

void  foo  () 
{ 
    Shape*  sp  = new Circle;
    Circle* cp  = sp->create();  
    cp->print();
    delete sp;
    delete cp;
}

The code is not compiling because Shape is not a Circle(downcasting error).

I am a little confused. The create() is not dynamic binding? the line

Circle* cp  = sp->create();  

not suppose to return a Circule*?

pointy
  • 21
  • 2

4 Answers4

2

It's because that line

Circle* cp = sp->create();

is evaluated at compile time by the compiler. And at compile time all it knows is that sp is a pointer to Shape therefore the signature for Shape::create() is used at compile time. It can't know what the pointer is pointing to because that is allocated and set at runtime. To get around it use a dynamic_cast.

Circle* cp = dynamic_cast<Circle*>(sp->create());

sashang
  • 11,704
  • 6
  • 44
  • 58
1

Downcasting is not implicit. Since you know what you are doing(i.e. sp is actually a circle), use dynamic_Cast

Circle* cp  = dynamic_cast<Circle*>(sp->create());
Gaurav Sehgal
  • 7,422
  • 2
  • 18
  • 34
1

You invoke create() on an instance that has the static type Shape. Hence, the function signature is Shape* create(). Indeed, after vtable lookup, the actual function invoked is Circle::create(), but the point of storing a Circle instance as a Shape reference is hiding the concrete type, its member functions and together with that possible covariant return types.

To obtain a Circle object via Circle::create(), you can either

Circle *c1 = new Circle; // Static type info (Circle) is preserved
Circle *c2 = c1->create();  // Ok, the covariant return type is Circle*

or

Shape *s1 = new Circle; // Everything Circle-related lost on the lhs
Circle *c1 = dynamic_cast<Circle*>(s1->create()); // Manually restore with RTTI

though the latter is rather a hint that something is wrong (why would you need to create subclass instances from a base class interface without hiding their concrete type?).

As a side note, you could also consider changing the function signature such that it returns a std::unique_ptr<Shape> or std::unique_ptr<Circle>, which is good practice for factory functions that return polymorphic class instances.

lubgr
  • 37,368
  • 3
  • 66
  • 117
0

Cast the shape pointer to a circle.

Circle* cp  = (Circle* sp)->create();  
Tbone281
  • 91
  • 1
  • 9