Polymorphic copy constructor

Ok. I am having a mind blank. But I am hoping there is an easy way to achieve what I want to do.

I have a vector<Parent*> that contains a collection of Child1-N* classes where each child inherits from Parent either directly, or indirectly (Nth-Level).

What I want to do is clone the contents of the vector invoking all the child copy constructors (yes, only require a shallow-copy) so I have 2 complete individual vectors with the same number, and type of objects that match parameters but are NOT pointing to the same memory space.

Some sample code showing what I mean:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <string>
#include <iostream>

using namespace std;

class Parent {
public:
  Parent() : name("Unknown") { }
  string name;
  virtual void foo() { cout << "Inside Parent" << endl; }
};

class Child: public Parent {
public:
  void foo() { cout << "Inside Child" << endl; }
};

int main() {

  Parent *P1, *P2;
  Child *C1 = new Child();

  P1 = C1;
  P1->name = "P1";
  P1->foo(); // Inside-Child C1

  P2 = &(*C1); // How to invoke a child's copy constructor here?
  // P2 = new Parent((*C1)); // Foo will then call Inside-Parent()
  P2->foo(); // Inside-Child C1
  P2->name = "P2";

  cout << P1->name << " & " << P2->name << endl; // Prints P2 & P2
  // Want it to print P1 and P2.

  // Ignore obvious memory leak
  return 0;
}


Some solutions I know of:
- dynamic_cast<> to each type of child until you hit a match, then invoke the individual constructor. Don't really like this idea because of the large amount of code that would need to be written.

- Create a CParent* Child::clone(ChildN*) function that will call it's own copy constructor and make it pure virtual on the parent.

Something easier and obvious I have missed?
Yes, the clone pattern is what you want, and is exactly as you described.
Hmm yea. The Prototype pattern (Clone to you ;)). I did really want to avoid that, but it does seem like the most efficient way. Buggar =\
For those wondering. My solution is going to be the Prototype pattern. It's the best method, but unfortunately requires a significant amount of code.

Here is my example code with it implemented:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <string>
#include <iostream>

using namespace std;

class Parent {
public:
  Parent() : name("Unknown") { }
  string name;
  virtual void foo() { cout << "Inside Parent" << endl; }
  virtual Parent* clone() = 0;
};

class Child: public Parent {
public:
  void foo() { cout << "Inside Child" << endl; }
  Parent* clone() { return new Child(*this); }
};

int main() {

  Parent *P1, *P2;
  Child *C1 = new Child();

  P1 = C1;
  P1->name = "P1";
  P1->foo(); // Inside-Child C1

  P2 = P1->clone();
  // P2 = new Parent((*C1)); // Foo will then call Inside-Parent()
  P2->foo(); // Inside-Child C1
  P2->name = "P2";

  cout << P1->name << " & " << P2->name << endl; // Prints P2 & P2
  // Want it to print P1 and P2.

  // Ignore obvious memory leak
  return 0;
}
Topic archived. No new replies allowed.