Topic: Clone for polymorph
Author: Christopher Eltschka <celtschk@web.de>
Date: Wed, 12 Dec 2001 19:15:21 GMT Raw View
Attila Feher <Attila.Feher@lmf.ericsson.se> writes:
> Hi,
>
> I am thinking lately about this ugly situ, that I have a pointer to a
> polymorph type, and I want to clone it. I mean:
>
> template<class T> T* clone( const T*v) {
> return new T(*v);
> }
>
> Or something like that. BUT, this will slice. And I do not like it.
>
> Some guys say it would be nice to have "virtual statics" to provide:
>
> class X {
> ...
> virtual static X clone( X*x) { return new X(*x); }
> };
>
> This is supposed to be virtual on its parameter... OK, nice, it gets
> into the class namespace etc. but I still do not like it! Why should I
> write this into every class I have? If I leave out one, and try to
> clone it, I will end up with something crippled.
Then use the following (IIRC, this solution for clone was first
suggested by Dietmar Kuehl):
template<class T> class Cloneable;
class CloneBase
{
template<class T> friend class Cloneable<T>;
public:
virtual void clone() = 0;
virtual ~CloneBase();
private:
class Lock;
virtual void unlock(Lock&) = 0;
};
template<class T> class Cloneable:
public T
{
public:
T* clone() { return new Cloneable<T>(*this); }
private:
void unlock(Lock&) {}
};
class Base: public CloneBase { ... };
// this is the base class of your hierarchy; no clone implemented
class Derived1: public Base { ... }; // all of them don't implement clone
class Derived2: public Base { ... };
class Derived3: public Derived2 { ... };
Now all those classes are abstract (because unlock() isn't implemented
and can't be due to private class Lock, and clone() isn't implemented
either), but you can create instances of Cloneable<Base>,
Cloneable<Derived1>, etc., and use them as Base, Derived1, etc.
For example, you could write:
Base* p = new Cloneable<Derived1>;
Base* p2 = p1->clone(); // creates a new Cloneable<Derived1>
This pattern can also be used to solve other problems, for example to
provide post-constructors and pre-destructors.
I call this the "base + template final" pattern, but maybe it already
has an official name.
The pattern has, however, some drawbacks.
The first is the problem of constructor forwarding (since constructors
are not inherited). Depending on your hierarchy, this may be simple of
complicated. The most general solution are forwarder templates.
The second drawback is specific to clone: You don't have covariant
return types with this pattern. Therefore you may have to use a cast
in certain situations (however, you can encapsulate it by using a
helper template like:
template<class T> T* clone(T* p) { return (T*)p->clone(); }
With this, you could also write
Derived1* p3 = clone(p);
If you put that template as friend into CloneBase (that is, define it
inline there), the lookup rules guarantee that it's only found if you
are dealing with the right hierarchy (and therefore you know by design
that this cast is safe).
[...]
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Sat, 17 Nov 2001 00:26:20 GMT Raw View
Attila.Feher@lmf.ericsson.se (Attila Feher) wrote (abridged):
> So my question is: why don't we have an operator clone [...]
I see clone as a specific example of a general need. For example, for
the Visitor pattern we currently have to write:
class BaseNode {
public:
virtual void accept( Visitor *v ) {
v->visit( this );
}
};
class SubNode : public BaseNode {
public:
virtual void accept( Visitor *v ) {
v->visit( this );
}
};
where the accept() routine has to be duplicated in every subclass.
Another example is where we need each subclass to have some static
memory, eg for a per-class counter.
I think we need a more general mechanism, to allow a base class to
inject arbitrary code into derived classes. The general mechanism could
then be used for clone().
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Attila Feher <Attila.Feher@lmf.ericsson.se>
Date: Sat, 17 Nov 2001 00:25:51 GMT Raw View
Adam Peterson wrote:
[SNIP]
> This is a scary thought. I like to make my classes copyable by default.
> (Usually it's not hard. They are unless I say otherwise.) But I'd think
> twice about that if I knew that making my class copyable imposes the
> requirement that all descendant classes be copyable. I think it's
> reasonable that some would be and some wouldn't.
Not with public inheritance! There you _must_ promise and provide the
_same_ interface as the base. This is the _whole_ idea. And the other
thing: _only_ for classes "declared virtual", where the cpc, op==, op=
etc. gets into the vtable.
> Perhaps by default descendants can be copyable or not copyable, but if a
> special tag attribute is put in a class, the compiler could require that all
> descendant classes be copyable.
That was the idea.
> However, I think it might be reasonable to
> suppose that some people would create an inheritance hierarchy and make a
> subclass for which a superclass was a semantic equivalent. Such a class
> should have the _option_, should it choose, to construct a sliced version of
> itself. Perhaps the only reason the base was subclassed in the first place
> was to provide some convenient constructors, and once the object is
> constructed, it really doesn't semantically matter if the object is sliced.
I do not get this. Slightly I see a danger here again: public
inheritance is for ISA realtionship, meaning that the I/F may be
extended but not shrinked.
Another issue is: if you add only convenient constructors, you won't get
slicing. Constructors are not data members.
Attila
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Michiel Salters<Michiel.Salters@cmg.nl>
Date: Sat, 17 Nov 2001 00:26:08 GMT Raw View
In article <3BF3022F.1060205@earthlink.net>, Edward Diener says...
>
>Attila Feher wrote:
>
>> Edward Diener wrote:
>> [SNIP]
>>
>>>I like the idea of an operator for cloning and find it useful. One thing
>>>is that the specs for this would have to define what would happen if no
>>>copy constructor exists for the cloned class. I would suggest in this
>>>case that an exception be thrown that is part of the C++ standard
>>>exception hierarchy. This would mimic the behavior of a failure of 'new'
>>>throwing std::bad_alloc.
>>>
>> Nope! Actually it does _not_ need it. Why? _Any_ derived class must
>> (IS-A) provide the _same_ interface as the class of the pointer we
>> provide there. So the compiler can decide: does class Base have a copy
>> constructor? If yes, _all_ derived classes must have - otherwise they
>> are not good for IS-A. So the compiler _can_ do the job if I am not
>> mistakin'. Now if a derived class does not have a copy constructor
>> implemented, one should get a sort of linker error...
Wrong; you missed private inheritance. That does not need to follow LSP.
>No, this is no good. Any class can decide not to have a public copy
>constructor to prevent copy from the outside or not to have a public or
>protected copy constructor to also prevent copy from a derived class.
>The copy constructor is overrideable in that sense that a derived class
>can hide it even if it is implemented publicly in a base class. Your
>clone needs the copy constructor for the polymorphic type of the actual
>object being cloned.
Hmm... In C++, protection is associated with interfaces, not actual types.
That is, if you have a polymorphic object hierarchy, with the base defining
public virtual functions, a derived class can make them private. However,
you can still call these functions virtually, by using the base class
interface.
The typical solution for the slicing problem is a public virtual function
clone() in the base class. Making that private in a derived class doesn't
prevent derived classes from being cloned.
Of course, the derived::clone() can be implemented as
{ throw cantclone(); }
HTH,
Michiel Salters
--
Michiel Salters
Consultant Technical Software Engineering
CMG Trade, Transport & Industry
Michiel.Salters@cmg.nl
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Attila Feher <Attila.Feher@lmf.ericsson.se>
Date: Sat, 17 Nov 2001 00:26:08 GMT Raw View
Edward Diener wrote:
[SNIP]
> No, this is no good. Any class can decide not to have a public copy
> constructor to prevent copy from the outside or not to have a public or
> protected copy constructor to also prevent copy from a derived class.
> The copy constructor is overrideable in that sense that a derived class
> can hide it even if it is implemented publicly in a base class.
In which case it _clearly_ breaks the rules of public inheritance.
> Your
> clone needs the copy constructor for the polymorphic type of the actual
> object being cloned.
Sure. That is the whole point.
> The compiler/linker does not know until run-time what the polymorphic
> pointer actually points to so no linker error can be given.
Not true. If one puts the copy constructors' address into the vtable
the same way as the other virtuals are added, it _can_ the same way as
it can for the other virtuals. BTW, as I have said, it need some syntax
to tell when the base class is declared, that it should be a "virtual"
class, having copy constructor(S) and probably several other things
(operator =, ==???) in its vtable.
> Your 'clone'
> is like a dynamic_cast, which must succeed or fail at run-time when the
> actually type of the object pointed to is known.
Nope. It is not necessarily. Only if you want it to be. I don't.
> Polymorphism is a
> run-time behavior, not a compile/linker time behavior.
Really? Then I have misunderstood something very badly about the
VTable. But I still think that it can be done. Maybe I am braindead.
:-))))
A
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Attila Feher <Attila.Feher@lmf.ericsson.se>
Date: Mon, 19 Nov 2001 16:54:44 GMT Raw View
Dave Harris wrote:
>
> Attila.Feher@lmf.ericsson.se (Attila Feher) wrote (abridged):
> > So my question is: why don't we have an operator clone [...]
>
> I see clone as a specific example of a general need. For example, for
> the Visitor pattern we currently have to write:
[SNIP]
> where the accept() routine has to be duplicated in every subclass.
> Another example is where we need each subclass to have some static
> memory, eg for a per-class counter.
Oh yeah. And here is when templates come into my mind...
> I think we need a more general mechanism, to allow a base class to
> inject arbitrary code into derived classes. The general mechanism could
> then be used for clone().
Agreed. I was
(nowadays I cannot sleep, someone I love choose to write into a media
newspaper over C++ programming. Is it a base for divorce in nowdayas
law? :-)))
Now anyways. I was _just_ thinking about a special kind of template, I
guess connected to this, but then I have felt asleep and forgot it until
now. What about a template mechanism templated by the classes type,
itself. Basically it is a special virtual function (or static variable
per class even), which is once introduced in a base class will be
generated for us in every subclass. Of course, the sublass would be
free to specialize it for itself! We could have: member functions,
member classes, and members for this purpose. Classes and members can
be good for the counting purpose, or anything you may need per class.
something like this as syntax:
class Base {
virtual
template<this T> T* clone() {
return new T(*this);
}
};
This would be the "virtual template", which is generated for every
instance of the class. The class clones itself. And any subclasses
would do the same, with their _own_ type.
Another one could be (still inside base):
template<this T> struct ClCtr {
static unsigned long ctr_;
};
Now to access the count we just type:
++ClCtr<OurType>::ctr_;
To access the counter in (one of) the base class(es):
++ClCtr<TheBaseIWant>::ctr_;
Now it would be also nice (for this counting purposes) that it would be
possible to achieve that Base will _only_ count its own instances and
not those of the descendants. But since when Base is being created it
has no idea about the fact that it is itself or a 10th descendant, it
makes it quite hard. Of course, descendants could access the bases'
counter and decrease it, but that is double work. This is one case,
when it would be good, if the base (constructor) would know, if it is
creating a Base object or a Derived one... This _may_ break OO from a
certain view, but I would say it is not. Just look at a Person object
next to you. You can be sure he _does_ behave differently as part of a
group/team and alone... Just a little philosophy, sorry. My point is,
it would be a sin, to make Base _exactly_ know what type it is part of,
but it may make sense to tell: it is now a base only.
BTW, little more about the syntax above:
Base says this as a rule for descendants:
template<this T> struct ClCtr {
ClCtr() : ctr_() { ; }
static void step() { ++ctr_; }
static std::size_t get() { return ctr_; }
private:
static std::size_t ctr_;
};
But it _may_ say also (sorry if the syntax is not OK, it wants to be
template specialization of one function of a template..., de idea is
the important here now):
template<> void ClCtr<Base>::step() { ; }
Why? Because - for this case - Base _knows_ it is an abstract class and
it has 0 instances itself.
This is just a bunch of ideas, they may even be dumb... Several
interesting questions arise. Eg: can the descendants change the
templated types totally? Could base actually _remove_ the counter,
since it does not need it? I cannot see now how and if it would make
sense at all.
But the point is: these stuff, (func,class,member(?)) templated on its
own type could be specialized in any/every class. Even the one
introducing it! And any descendants.
Sounds cool. Question is rather how to define it to make perfect sense,
to be implementable (preferably easily)... Does it make sense to you
guys, or I should try to sleep more? :-))
A
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Mon, 19 Nov 2001 16:55:00 GMT Raw View
Attila.Feher@lmf.ericsson.se (Attila Feher) wrote (abridged):
> > No, this is no good. Any class can decide not to have a public copy
> > constructor to prevent copy from the outside or not to have a public
> > or protected copy constructor to also prevent copy from a
> > derived class. The copy constructor is overrideable in that sense
> > that a derived class can hide it even if it is implemented publicly
> > in a base class.
>
> In which case it _clearly_ breaks the rules of public inheritance.
Not really. The reason being, constructors are not invoked on instances of
the class. They are invoked on raw storage. So they don't effect whether
instances are substitutable.
If C++ had a meta-class system, constructors would belong to the
meta-class and we could talk about whether one meta-class had publicly
inherited from another meta-class without implementing its interface. C++
doesn't have meta-classes but it may help to think in those terms.
Another issue is that the copy constructor of a derived class cannot
possibly belong to the base class's interface because it takes an argument
of different type. Eg:
class Base {
public:
Base( const Base &rhs );
};
class Derived : public Base {
public:
Derived( const Derived &rhs );
};
Notice how the constructor arguments differ. Contrast with:
class Derived : public Base {
public:
Derived( const Derived &rhs );
Derived( const Base &rhs );
};
where the second constructor is (a) not what we really want and (b) not
really a copy constructor.
> If one puts the copy constructors' address into the vtable the same
> way as the other virtuals are added, it _can_ the same way as it can
> for the other virtuals.
The vtable needs the address of a clone() function, not the address of a
copy constructor. That's doable. I agree a clone() function can be
compiler-generated from a copy constructor, if there is one.
I'm not sure this is worth doing just for clone(), as I said elsewhere.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Richard Smith" <richard@ex-parrot.com>
Date: Tue, 20 Nov 2001 19:16:04 GMT Raw View
"Dave Harris" <brangdon@cix.co.uk> wrote in message
news:memo.20011117165247.12747N@brangdon.madasafish.com...
> Attila.Feher@lmf.ericsson.se (Attila Feher) wrote (abridged):
[ ... ]
> > If one puts the copy constructors' address into the vtable the same
> > way as the other virtuals are added, it _can_ the same way as it can
> > for the other virtuals.
>
> The vtable needs the address of a clone() function, not the address of a
> copy constructor. That's doable. I agree a clone() function can be
> compiler-generated from a copy constructor, if there is one.
>
> I'm not sure this is worth doing just for clone(), as I said elsewhere.
In today's language, we can get this effect by putting a method of the form
class T {
// ...
virtual T *clone() const { return new T(*this); }
into every class. The main problem with this is that if someone forgets to
override this member in any class in a hierarchy, you get slicing. The
other, more minor, problem is that you end up writing the same code in each
class of the hierarchy. These are issues that occur in a number of
different contexts, for example, the visitor pattern requires something like
class T {
// ...
virtual void visit(visitor &v) { v.accept(*this); }
I think a general solution to these two problems would be much more useful
than a special-case solution for cloning. The former problem could easily
be solved with an attribute to say "this function must be overriden". A
solution to the latter problem would also be nice. The first problem is to
write clone function in such a way that it doesn't use the name of the class
at all. This could be done using the typeof operator (if it is added):
class T {
// ...
virtual boost::remove_const<typeof(*this)>::type *clone() const
{ return new boost::remove_const<typeof(*this)>::type(*this); }
And then you'd just need some syntax to insert the code fragment into every
derived class. It seems fashionable to suggest combining two other keywords
for new concepts, and "auto virtual" seems fairly apt. ... and with the aid
of a helper class:
class clonable {
public:
auto virtual boost::remove_const<typeof(*this)>::type *clone() const
{ return new boost::remove_const<typeof(*this)>::type(*this); }
};
class base_of_my_hierarchy : public cloneable {
// ...
IMO, such a solution would have much more general applicability than a
implicit clone function would do.
If a "dynamic_new" function was wanted, then it is possible, even in today's
language, to write a template function that calls the the clone function if
such a function exists, and otherwise just makes a copy using new.
--
Richard Smith
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Johan Ericsson" <livedog65@hotmail.com>
Date: Tue, 20 Nov 2001 19:33:54 GMT Raw View
> I do not know how frequently objects needs to be cloned. But I hate
> boring tasks, where people can make mistakes - like writing a clone
> function for every object, which ever needs to be cloned.
I've written a class that wraps a type and injects the clone() function so
that one doesn't need to write the clone() function all over the place. Its
usage is shown below its definition. Perhaps this would be sufficient for
your needs? After the class is wrapped it can be placed in STL containers,
without fear of slicing. Interestingly, the client class also no longer
needs a virtual destructor.
It is a simplified version of Peter Dimov's variant class at boost:
http://groups.yahoo.com/group/boost/files/impl_ptr/variant.hpp
#include <iostream>
#include <vector>
#include <algorithm>
template <class T>
class poly_ptr
{
class place_holder
{
public:
virtual place_holder* clone() const = 0;
virtual ~place_holder() {}
virtual T* get_element() = 0;
virtual const T* get_element() const= 0;
};
template <class U>
class held : public place_holder
{
public:
held(const U& u) :m_U(u){}
place_holder* clone() const {return new held(*this);}
T* get_element() {return &m_U;}
const T* get_element() const {return &m_U;}
U m_U;
};
place_holder * m_p;
public:
template <class U> //Conversion constructor
poly_ptr(const U& u):m_p(new held<U>(u)){}
// Copy Constructor
poly_ptr(const poly_ptr& p):m_p(p.m_p->clone()){}
const poly_ptr& operator=(poly_ptr p)
{
swap(p);
return *this;
}
T* operator->() {return m_p->get_element();}
const T* operator->() const {return m_p->get_element();}
T& operator*() {return *m_p->get_element();}
const T& operator*() const {return *m_p->get_element();}
~poly_ptr(){delete m_p;}
void swap(poly_ptr& p)
{
std::swap(p.m_p,m_p);
}
};
class Parent
{
public:
virtual void out() = 0;
};
class Child : public Parent
{
void out() {std::cout << "Hi there" << std::endl;}
};
class Child2 : public Parent
{
void out() {std::cout << "Hi there2" << std::endl;}
};
int main()
{
Child c;
poly_ptr<Parent> p(c);
std::vector<poly_ptr<Parent> > vec(10,c);
vec.push_back(Child2());
int i;
for (i=0;i<vec.size();i++)
{
vec[i]->out();
}
return 0;
}
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Edward Diener <eldiener@earthlink.net>
Date: Wed, 14 Nov 2001 10:19:33 GMT Raw View
Attila Feher wrote:
> Hi,
>
> I am thinking lately about this ugly situ, that I have a pointer to a
> polymorph type, and I want to clone it. I mean:
>
> template<class T> T* clone( const T*v) {
> return new T(*v);
> }
>
> Or something like that. BUT, this will slice. And I do not like it.
>
> Some guys say it would be nice to have "virtual statics" to provide:
>
> class X {
> ...
> virtual static X clone( X*x) { return new X(*x); }
> };
>
> This is supposed to be virtual on its parameter... OK, nice, it gets
> into the class namespace etc. but I still do not like it! Why should I
> write this into every class I have? If I leave out one, and try to
> clone it, I will end up with something crippled.
>
> So my question is: why don't we have an operator clone (like operator
> new), taking a pointer to a (polymorph) type as parameter, and returning
> a new object, created from the real (dynamic) type of the pointer. I
> believe that the compiler would have no problem with it. I guess nearly
> everything is already done to support is when dynamic_cast was done.
>
> I do not know how frequently objects needs to be cloned. But I hate
> boring tasks, where people can make mistakes - like writing a clone
> function for every object, which ever needs to be cloned.
>
> Do you guys think, that something like this operator clone could be
> implemented?
>
> Base *der = new Derived();
> Base * cloned = clone der;
>
> And after this, cloned points to a Derived object, created by operator
> new and constructed by Derived copy constructor.
>
> I guess it sounds good. Of course, whatever like this will be ever
> implemented, cannot be called clone, since making clone a reserved word
> would drive half of the world crazy. How about dynamic_new ? :-))))
>
I like the idea of an operator for cloning and find it useful. One thing
is that the specs for this would have to define what would happen if no
copy constructor exists for the cloned class. I would suggest in this
case that an exception be thrown that is part of the C++ standard
exception hierarchy. This would mimic the behavior of a failure of 'new'
throwing std::bad_alloc.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Attila Feher <Attila.Feher@lmf.ericsson.se>
Date: Wed, 14 Nov 2001 23:19:11 GMT Raw View
Edward Diener wrote:
[SNIP]
> I like the idea of an operator for cloning and find it useful. One thing
> is that the specs for this would have to define what would happen if no
> copy constructor exists for the cloned class. I would suggest in this
> case that an exception be thrown that is part of the C++ standard
> exception hierarchy. This would mimic the behavior of a failure of 'new'
> throwing std::bad_alloc.
Nope! Actually it does _not_ need it. Why? _Any_ derived class must
(IS-A) provide the _same_ interface as the class of the pointer we
provide there. So the compiler can decide: does class Base have a copy
constructor? If yes, _all_ derived classes must have - otherwise they
are not good for IS-A. So the compiler _can_ do the job if I am not
mistakin'. Now if a derived class does not have a copy constructor
implemented, one should get a sort of linker error...
I did not think much about the implications or implementation. Probably
there is some "trick" needed to ensure that a copy constructor exists
for all derived type - at compile or link time. To be honest I have no
idea how...
One can (of course) add the copy constructor to the VTABLE and use it
from there... and if it is not defined, than there will be a sort of
error message from the linker as it is ususal for the missing virtuals.
But of course, it would be stupid to do it for all the classes...
Tricky one. One could say that if I declare my class virtual, then I
have it?
virtual Base {
};
Virtual would mean here: put some more stuff into the VTABLE (like copy
constructor, operator(s)???? etc.)
Maybe I walk now a path, which the original creators did walk and gave
up. Anyone jumping in with info?
Attila
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Edward Diener <eldiener@earthlink.net>
Date: Thu, 15 Nov 2001 16:56:32 GMT Raw View
Attila Feher wrote:
> Edward Diener wrote:
> [SNIP]
>
>>I like the idea of an operator for cloning and find it useful. One thing
>>is that the specs for this would have to define what would happen if no
>>copy constructor exists for the cloned class. I would suggest in this
>>case that an exception be thrown that is part of the C++ standard
>>exception hierarchy. This would mimic the behavior of a failure of 'new'
>>throwing std::bad_alloc.
>>
>
> Nope! Actually it does _not_ need it. Why? _Any_ derived class must
> (IS-A) provide the _same_ interface as the class of the pointer we
> provide there. So the compiler can decide: does class Base have a copy
> constructor? If yes, _all_ derived classes must have - otherwise they
> are not good for IS-A. So the compiler _can_ do the job if I am not
> mistakin'. Now if a derived class does not have a copy constructor
> implemented, one should get a sort of linker error...
>
No, this is no good. Any class can decide not to have a public copy
constructor to prevent copy from the outside or not to have a public or
protected copy constructor to also prevent copy from a derived class.
The copy constructor is overrideable in that sense that a derived class
can hide it even if it is implemented publicly in a base class. Your
clone needs the copy constructor for the polymorphic type of the actual
object being cloned.
The compiler/linker does not know until run-time what the polymorphic
pointer actually points to so no linker error can be given. Your 'clone'
is like a dynamic_cast, which must succeed or fail at run-time when the
actually type of the object pointed to is known. Polymorphism is a
run-time behavior, not a compile/linker time behavior.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Adam Peterson <ahp6@email.byu.edu>
Date: Thu, 15 Nov 2001 21:19:35 GMT Raw View
"Attila Feher" <Attila.Feher@lmf.ericsson.se> wrote in message
news:3BF25E51.B56D816B@lmf.ericsson.se...
> Edward Diener wrote:
> [SNIP]
> > I like the idea of an operator for cloning and find it useful. One thing
> > is that the specs for this would have to define what would happen if no
> > copy constructor exists for the cloned class. I would suggest in this
> > case that an exception be thrown that is part of the C++ standard
> > exception hierarchy. This would mimic the behavior of a failure of 'new'
> > throwing std::bad_alloc.
>
> Nope! Actually it does _not_ need it. Why? _Any_ derived class must
> (IS-A) provide the _same_ interface as the class of the pointer we
> provide there. So the compiler can decide: does class Base have a copy
> constructor? If yes, _all_ derived classes must have - otherwise they
> are not good for IS-A. So the compiler _can_ do the job if I am not
> mistakin'. Now if a derived class does not have a copy constructor
> implemented, one should get a sort of linker error...
This is a scary thought. I like to make my classes copyable by default.
(Usually it's not hard. They are unless I say otherwise.) But I'd think
twice about that if I knew that making my class copyable imposes the
requirement that all descendant classes be copyable. I think it's
reasonable that some would be and some wouldn't.
Perhaps by default descendants can be copyable or not copyable, but if a
special tag attribute is put in a class, the compiler could require that all
descendant classes be copyable. However, I think it might be reasonable to
suppose that some people would create an inheritance hierarchy and make a
subclass for which a superclass was a semantic equivalent. Such a class
should have the _option_, should it choose, to construct a sliced version of
itself. Perhaps the only reason the base was subclassed in the first place
was to provide some convenient constructors, and once the object is
constructed, it really doesn't semantically matter if the object is sliced.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Attila Feher <Attila.Feher@lmf.ericsson.se>
Date: Tue, 13 Nov 2001 01:44:36 GMT Raw View
Hi,
I am thinking lately about this ugly situ, that I have a pointer to a
polymorph type, and I want to clone it. I mean:
template<class T> T* clone( const T*v) {
return new T(*v);
}
Or something like that. BUT, this will slice. And I do not like it.
Some guys say it would be nice to have "virtual statics" to provide:
class X {
...
virtual static X clone( X*x) { return new X(*x); }
};
This is supposed to be virtual on its parameter... OK, nice, it gets
into the class namespace etc. but I still do not like it! Why should I
write this into every class I have? If I leave out one, and try to
clone it, I will end up with something crippled.
So my question is: why don't we have an operator clone (like operator
new), taking a pointer to a (polymorph) type as parameter, and returning
a new object, created from the real (dynamic) type of the pointer. I
believe that the compiler would have no problem with it. I guess nearly
everything is already done to support is when dynamic_cast was done.
I do not know how frequently objects needs to be cloned. But I hate
boring tasks, where people can make mistakes - like writing a clone
function for every object, which ever needs to be cloned.
Do you guys think, that something like this operator clone could be
implemented?
Base *der = new Derived();
Base * cloned = clone der;
And after this, cloned points to a Derived object, created by operator
new and constructed by Derived copy constructor.
I guess it sounds good. Of course, whatever like this will be ever
implemented, cannot be called clone, since making clone a reserved word
would drive half of the world crazy. How about dynamic_new ? :-))))
Attila
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]