1

I am having some trouble with trying to create a copy of a class from a pointer to its base class. It is best illustrated through this example:

#include <iostream>
#include <vector>

class Base {
  public:
    Base() { }
    virtual void test() { std::cout << "I am just the base class\n"; }
};

class First : public Base {
  public:
    First() { }
    void test() { std::cout << "This is the First class\n"; }
};

class Second : public Base {
  public:
    Second() { }
    void test() { std::cout << "This is the Second class\n"; }
};

int main() {
  First *f = new First();
  Second *s = new Second();

  // First, I keep a vector of pointers to their base class
  std::vector<Base *> ptrs;
  ptrs.push_back(f);
  ptrs.push_back(s);
  ptrs[0]->test();    // Properly calls the implemented virtual class by inheritor
  ptrs[1]->test();    // Properly calls the implemented virtual class by inheritor

  // Now, I want to *copy* the class without it being spliced to just the base class
  // from the ptrs vector (not from 'f')
  First *f2 = new First(*ptrs[0]);
}

The error I end up getting is:

test.cpp: In function ‘int main()’:
test.cpp:35: error: no matching function for call to ‘First::First(Base&)’
test.cpp:12: note: candidates are: First::First()
test.cpp:10: note:                 First::First(const First&)

Is there any way to cast this pointer to copy the full objected, and not just the base class? Or do I need to store a pointer to the inheritor to make this work?

gnychis
  • 7,289
  • 18
  • 75
  • 113

2 Answers2

3

You can do this:

First *f2 = 0;
if ( typeid(*ptrs[0]) == typeid(First))
   f2 = new First(*dynamic_cast<First*>(ptrs[0]));

That should work.

But a better approach is to have clone() virtual function in the base class, and implement it the derived class:

class Base 
{
  public:
    virtual ~Base() { } //virtual destructed added by me!
    virtual Base *clone() = 0;
};

class First : public Base 
{
  public:
    virtual First *clone() { /* implement it */ }  //Covariant return type
};

And

First *f2 = 0;
if ( typeid(*ptrs[0]) == typeid(First))
   f2 = ptrs[0]->clone(); //no need to use new

Two points to be noted:

  • I have added virtual destructor to the Base class. See this topic to know why you probably need it.
  • I have used different return type for clone() in the derived class. It is called covariant return type.
Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851
1
First *fx=(First*)ptrs[0];
First *f2 = new First(*fx); 
david
  • 485
  • 1
  • 4
  • 10