views:

54

answers:

4

I have a base class A and classes B and C are derived from it. A is an abstract class, and all three classes have a constructor that takes 2 arguments. Is it possible to make a method in the base class A like this:

A* clone() const
{
    return new this.GetType(value1, value2);
}

and if the current object whose clone()-function is being called is for example C, the function will return the pointer to a new object of class type C?

+1  A: 

Make clone() virtual and have subclasses B and C implement their own version of clone() and return a new instance of themselves.

birryree
+2  A: 

You need to make clone() a virtual function and override it in class C, like so:

class A
{
public:
    virtual A* clone() const  {  return new A(v1, v2);  }
}

class C : public A
{
public:
    virtual A* clone() const  {  return new C(v1, v2);  }
}
mskfisher
+2  A: 

This looks like C++.NET (a.k.a. "managed C++") rather than plain (standard) C++. I'm not an expert on this, but my guess (assuming .NET) would be that you'd have to use reflection to instantiate an object of a System.Type. The usual steps are:

  1. Create or get a suitable Type object, e.g. by calling GetType.
  2. Find a suitable ConstructorInfo (Type.GetConstructors() IIRC)
  3. Call ConstructorInfo.Invoke() to create an instance
  4. Cast the resulting System.Object to the desired type.

In regular C++, you can't do this at all, because the language simply doesn't have reflection, and type information is mostly lost at run time (RTTI can compare and test run-time types of objects, but that's about it). You'll have to implement a new clone method for each derived class; the pattern I usually use looks something like this:

class Foobar : public Baz {
  public:
    int extra; // public for demonstration purposes

    // Copy constructor takes care of actual copying
    Foobar(const Foobar& rhs) : Baz(rhs), extra(rhs.extra) { }

    // clone() uses copy constructor to create identical instance.
    // Note that the return type is Baz*, not Foobar*, so that inheritance works
    // as expected.
    virtual Baz* clone() const { return new Foobar(*this); }
};
tdammers
How would the opposite make any sense at all?
tdammers
+1  A: 

Nothing particularly wrong with the other answers, but if I was assuming all subclasses of A could be clone()ed just by constructing with two parameters, then I'd do it like this:

class A
{
  public:
    A* clone() const  { return create(value1, value2); }
  private:
    virtual A* create(Type1 v1, Type2 v2) const { return new A(v1, v2); }
};

class C : public A
{
    virtual C* create(Type1 v1, Type2 v2) const { return new C(v1, v2); }
};

If nothing else, this means that value1 and value2 don't need to be accessible in class C - they could be private members. If they're non-trivial expressions, they don't need to be repeated in C either.

That's a bit of a dubious assumption, though - more likely you'd want clone() to use the derived class's copy constructor, as in tdammers's answer.

Steve Jessop