kc@rna.UUCP (Kaare Christian) (05/02/90)
I recently needed to make a copy (a clone) of a class object, given only a base class pointer to the object. C++ lets you do some things with a class, knowing only its base type, but it doesn't provide an easy way to make a copy. My solution was to make a virtual member function that returned the size of each of the derived classes, and then make an operator= function (left arg, ref pointer to base, right arg, ref to base) that did the work - it called the size fn of the right operand to determine how much space was needed, allocated it, did a bitwise copy, then did some housekeeping. Shouldn't this be easier? Given a (base *) pointer to a derived object, I think it should be easy to make a copy of the thing pointed at. One way might be to add a clone facility, that would be used equivalently to new, but that would duplicate an existing object. Base *p = ... ; Base *b; b = clone *p; // new takes a type, clone takes an object Another method might be to have a typeof builtin, perhaps similar to the following: Base *p = .... ; Base *b; b = new typeof(*p); // allocates space *(typeof(*p) *)b = *(typeof(*p) *)p; // ugly, but copies whole thing Kaare Christian kc@rna.rockefeller.edu
jbuck@carson.berkeley.edu (Joe Buck) (05/03/90)
In article <1019@rna.UUCP>, kc@rna.UUCP (Kaare Christian) writes: > I recently needed to make a copy (a clone) of a class object, given only a > base class pointer to the object. C++ lets you do some things with a class, > knowing only its base type, but it doesn't provide an easy way to make > a copy. My solution was to make a virtual member function that > returned the size of each of the derived classes, and then make an > operator= function (left arg, ref pointer to base, right arg, ref to > base) that did the work - it called the size fn of the right operand to > determine how much space was needed, allocated it, did a bitwise copy, > then did some housekeeping. You're working too hard. All you really need to do is call the copy constructor from a virtual function. In the base class (I'll assume it's virtual) do class BaseType { virtual BaseType* copy () = 0; } For EACH derived class you must redefine the copy function, as follows. BaseType* DerivedType::copy () { return new DerivedType(*this); } If your BaseType isn't a virtual base class, then you'd define copy in the base class to return new BaseType(*this). This is simple; it calls the copy constructor for the appropriate type to do the copy. This assumes either that the default copy constructor will do, or that you've defined copy constructors when they won't. -- Joe Buck jbuck@ohm.berkeley.edu {uunet,ucbvax}!ohm.berkeley.edu!jbuck
roger@procase.UUCP (Roger H. Scott) (05/05/90)
In article <1019@rna.UUCP> kc@rna.UUCP (Kaare Christian) writes: >I recently needed to make a copy (a clone) of a class object, given only a >base class pointer to the object. C++ lets you do some things with a class, >knowing only its base type, but it doesn't provide an easy way to make >a copy. I suppose that depends almost entirely on how you define "easy". Do you mean something easier than the following?: class Base { public: Base(); Base(Base&); virtual Base *clone() {return new Base(*this);} }; class Derived : public Base { public: Derived(); Derived(Derived&); Base *clone() {return new Derived(*this); }; ... Base *p = ...; Base *another_just_like_p = p->clone(); >... >One way might be to add a clone facility, that would be used equivalently >to new, but that would duplicate an existing object. The problem here is the word "duplicate". It is rarely the case that a logical "clone" of an object is simply a bit-wise copy (a.k.a. shallow copy). Sometimes what you want is a clone of an entire structure (a.k.a deep copy). > Base *p = ... ; > Base *b; > b = clone *p; // new takes a type, clone takes an object > >Another method might be to have a typeof builtin, perhaps similar to the >following: > Base *p = .... ; > Base *b; > b = new typeof(*p); // allocates space > *(typeof(*p) *)b = *(typeof(*p) *)p; // ugly, but copies whole thing Both of these schemes suffer from the same problem: *in general*, a C++ compiler does not know the type of the object that a pointer points to. In order to fix this the definition of the language would have to be changed so that *all* objects were guaranteed to encode their own type in some manner or other. The fact that this is not so is not immediately obvious from the language definition (as opposed to from well-known implementations), but it can be inferred from the conformance of C++ structs to C structs and the equivalence of C++ classes to C++ structs. I.M.H.O. the biggest mistake made in the design of C++ was the equivalence of classes and structs.
horstman@sjsumcs.sjsu.edu (Cay Horstmann) (05/05/90)
In article <1019@rna.UUCP> kc@rna.UUCP (Kaare Christian) writes: >I recently needed to make a copy (a clone) of a class object, given only a >base class pointer to the object. C++ lets you do some things with a class, >knowing only its base type, but it doesn't provide an easy way to make >a copy. My solution was to make a virtual member function that >returned the size of each of the derived classes, and then make an >operator= function (left arg, ref pointer to base, right arg, ref to >base) that did the work - it called the size fn of the right operand to >determine how much space was needed, allocated it, did a bitwise copy, >then did some housekeeping. > That appears to be a very dangerous thing to do in general. Many classes need more than bitwise copying for correct behavior (e.g. when using ref counts.) What if someone derives from your stuff, faithfully supplies the size function and adds a data member with nontrivial copy semantics? Cay