1

The following code is giving compilation error as : "cannot convert from 'Cloneable*' to 'AClass*'" in Line 1. As per my knowledge, it deals with the concepts of compile time and run time polymorphism.But I do not have a concrete reasoning on this.Kindly help.

struct Cloneable
{
 virtual Cloneable* clone()
  {
  cout << "Cloneable";
  return new Cloneable;
  }

  virtual ~Cloneable() {}
};


struct AClass : public Cloneable
{
  virtual AClass* clone()
  {
  cout << "AClass";
  return new AClass;
  }
};

int main()
{ 
 Cloneable* s1 = new AClass;
 AClass* s2 = s1->clone();      //Line 1
return 0;
}
Ishita
  • 489
  • 5
  • 15

3 Answers3

1

Basically, when you store your new AClass* in your base class pointer, the result of calling clone will be a Cloneable*, which would need to be downcast into a AClass*, which may not always be safe. Hence the compiler will want a dynamic_cast ()

muhmud
  • 4,474
  • 2
  • 15
  • 22
  • @muhmud... This code will work fine if I use static_cast() ( to cast a base class pointer type to derived class pointer type).Modifying Line 1 as : AClass* s2 = static_cast(s1->clone());.What I really want to know is, how the compiler interprets this code. – Ishita Feb 27 '13 at 19:31
  • @user2100866 - You should have a look at this - http://stackoverflow.com/questions/28002/regular-cast-vs-static-cast-vs-dynamic-cast. `dynamic_cast()` does runtime checks during downcasting that can prevent undefined behaviour. – muhmud Feb 27 '13 at 20:20
1

While it's possible to just make it "work" with cast it's very dangerous what you are doing. You forgot to delete two dynamically allocated objects. It's also not so good idea to "hide dynamic memory allocation" like this, espacially that you don't delete it anywhere. Would be just much easier to use std::unique_ptr or std::shared_ptr or simply just allocate objects on the stack.

Edit: My apology for not giving straight answer first:

AClass* s2 = dynamic_cast<AClass*>(s1->clone()); 
Lufi
  • 161
  • 1
  • 1
  • 3
1

You are calling clone() on a Cloneable pointer. This method returns aCloneable*, so you need this:

Cloneable* s2 = s1->clone();

This will instantiate an AClass. This is the standard way to use this clone idiom. If you are using polymorphism correctly, it shouldn't matter if you have a Cloneable* or an AClass*. Hence, you would usually return Cloneable* from AClass::clone() too. Preferably, you would return a smart pointer, of course.

struct AClass
{
  virtual std::unique_ptr<Cloneable> clone();
};

struct AClass : public Cloneable
{
  virtual std::unique_ptr<Cloneable> clone();
};
juanchopanza
  • 223,364
  • 34
  • 402
  • 480