Cloning C++ objects

Discussion in 'C++' started by pazabo@gmail.com, Dec 4, 2006.

  1. Guest

    Hi,

    I'm trying to somehow implement polymorphic object cloning (just as it
    is in Java), but when I write:

    class Object {
    public:
    virtual Object * clone() const = 0;
    // ...
    }

    class String : public Object {
    public:
    Object * clone() const { return new String(*this); }
    // ...
    }

    compiler tells me, that I cannot allocate object of class String,
    because some methods are "pure". There are some more virtual methods in
    Object, but there are all implemented in String. What should I do to
    solve this problem?

    Paul PAZABO Zaborski
    , Dec 4, 2006
    #1
    1. Advertising

  2. mlimber Guest

    wrote:
    > Hi,
    >
    > I'm trying to somehow implement polymorphic object cloning (just as it
    > is in Java), but when I write:
    >
    > class Object {
    > public:
    > virtual Object * clone() const = 0;
    > // ...
    > }
    >
    > class String : public Object {
    > public:
    > Object * clone() const { return new String(*this); }
    > // ...
    > }
    >
    > compiler tells me, that I cannot allocate object of class String,
    > because some methods are "pure". There are some more virtual methods in
    > Object, but there are all implemented in String. What should I do to
    > solve this problem?


    It's likely that you forgot to implement something from Object (or that
    you added a pure virtual function in String). Post more code, and we
    can probably tell you what the problem is.

    Cheers! --M
    mlimber, Dec 4, 2006
    #2
    1. Advertising

  3. Guest

    mlimber wrote:
    > wrote:
    > > Hi,
    > >
    > > I'm trying to somehow implement polymorphic object cloning (just as it
    > > is in Java), but when I write:
    > >
    > > class Object {
    > > public:
    > > virtual Object * clone() const = 0;
    > > // ...
    > > }
    > >
    > > class String : public Object {
    > > public:
    > > Object * clone() const { return new String(*this); }
    > > // ...
    > > }
    > >
    > > compiler tells me, that I cannot allocate object of class String,
    > > because some methods are "pure". There are some more virtual methods in
    > > Object, but there are all implemented in String. What should I do to
    > > solve this problem?

    >
    > It's likely that you forgot to implement something from Object (or that
    > you added a pure virtual function in String). Post more code, and we
    > can probably tell you what the problem is.
    >
    > Cheers! --M


    Oh.. I see the problem.. I put "const" after some methods in Object,
    but I forgot to do it in String, so compiler considered it as abstract
    class.
    Anyway, thanks for help :)
    , Dec 4, 2006
    #3
  4. schrieb:
    > Hi,
    >
    > I'm trying to somehow implement polymorphic object cloning (just as it
    > is in Java), but when I write:
    >
    > class Object {
    > public:
    > virtual Object * clone() const = 0;
    > // ...
    > }
    >
    > class String : public Object {
    > public:
    > Object * clone() const { return new String(*this); }


    I would return a String* here:

    String* clone() const { return new String(*this); }

    So you can clone a String and get a String without casting.

    > // ...
    > }


    --
    Thomas
    http://www.netmeister.org/news/learn2quote.html
    Thomas J. Gritzan, Dec 5, 2006
    #4
  5. Thomas J. Gritzan wrote:
    > schrieb:
    > > Hi,
    > >
    > > I'm trying to somehow implement polymorphic object cloning (just as it
    > > is in Java), but when I write:
    > >
    > > class Object {
    > > public:
    > > virtual Object * clone() const = 0;
    > > // ...
    > > }
    > >
    > > class String : public Object {
    > > public:
    > > Object * clone() const { return new String(*this); }

    >
    > I would return a String* here:
    >
    > String* clone() const { return new String(*this); }
    >
    > So you can clone a String and get a String without casting.



    Generally, the reason to want to implement a virtual clone() type
    method is when you are dealing with polymorphic objects and aren't (or
    don't want to be) aware of their exact types. You are generally
    dealing with pointers to base classes that define clone() in terms of
    themselves. If you already knew the type of the object why wouldn't
    you just invoke new with a copy constructor?

    Regards,

    Jon Trauntvein
    JH Trauntvein, Dec 5, 2006
    #5
  6. Pete Becker Guest

    JH Trauntvein wrote:
    >>>
    >>> class Object {
    >>> public:
    >>> virtual Object * clone() const = 0;
    >>> // ...
    >>> }
    >>>
    >>> class String : public Object {
    >>> public:
    >>> Object * clone() const { return new String(*this); }

    >> I would return a String* here:
    >>
    >> String* clone() const { return new String(*this); }
    >>
    >> So you can clone a String and get a String without casting.

    >
    >
    > Generally, the reason to want to implement a virtual clone() type
    > method is when you are dealing with polymorphic objects and aren't (or
    > don't want to be) aware of their exact types. You are generally
    > dealing with pointers to base classes that define clone() in terms of
    > themselves. If you already knew the type of the object why wouldn't
    > you just invoke new with a copy constructor?
    >


    I was going to say the same thing, but in general, it's a little more
    complicated. Suppose there's a class derived from String, and you've got
    a String*. Then having String::clone() return a String* is handy,
    because you can clone the object that the String* points to without
    having to cast the returned pointer back from Object*.

    --

    -- Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com)
    Author of "The Standard C++ Library Extensions: a Tutorial and
    Reference." (www.petebecker.com/tr1book)
    Pete Becker, Dec 5, 2006
    #6
  7. Guest

    On Dec 5, 1:20 pm, "JH Trauntvein" <> wrote:
    > Thomas J. Gritzan wrote:
    > > schrieb:
    > > > Hi,

    >
    > > > I'm trying to somehow implement polymorphic object cloning (just as it
    > > > is in Java), but when I write:

    >
    > > > class Object {
    > > > public:
    > > > virtual Object * clone() const = 0;
    > > > // ...
    > > > }

    >
    > > > class String : public Object {
    > > > public:
    > > > Object * clone() const { return new String(*this); }

    >
    > > I would return a String* here:

    >
    > > String* clone() const { return new String(*this); }

    >
    > > So you can clone a String and get a String without casting.Generally, the reason to want to implement a virtual clone() type

    > method is when you are dealing with polymorphic objects and aren't (or
    > don't want to be) aware of their exact types. You are generally
    > dealing with pointers to base classes that define clone() in terms of
    > themselves. If you already knew the type of the object why wouldn't
    > you just invoke new with a copy constructor?


    Which means that you have something like this:
    struct Object {
    virtual Object* clone() {
    std::cout << "obj\n";
    return new Object(*this);
    }
    };

    struct String : public Object {
    int a;
    virtual String* clone() {
    std::cout << "str\n";
    return new String(*this);
    }
    };

    int main() {
    String* str = new String;
    Object* obj1 = str;
    Object* obj2 = obj1->clone();
    }

    As you see if you run the code it's the String::clone() function that
    is called, even tough you didn't know that it was a String. If you
    didn't use the String::clone() you would not have been able to create a
    clone since there is no 'a'-variable in Object, so when calling the
    copy-constructor of Object you get an Object and not a String. In other
    words, returning a String* does not prevent you from cloning a String
    from an Object-pointer, but allows you to clone a String also from a
    String-pointer.

    --
    Erik Wikström
    , Dec 5, 2006
    #7
  8. wrote:
    >
    > Which means that you have something like this:
    > struct Object {
    > virtual Object* clone() {
    > std::cout << "obj\n";
    > return new Object(*this);
    > }
    > };
    >
    > struct String : public Object {
    > int a;
    > virtual String* clone() {
    > std::cout << "str\n";
    > return new String(*this);
    > }
    > };
    >
    > int main() {
    > String* str = new String;
    > Object* obj1 = str;
    > Object* obj2 = obj1->clone();
    > }
    >
    > As you see if you run the code it's the String::clone() function that
    > is called, even tough you didn't know that it was a String. If you
    > didn't use the String::clone() you would not have been able to create a
    > clone since there is no 'a'-variable in Object, so when calling the
    > copy-constructor of Object you get an Object and not a String. In other
    > words, returning a String* does not prevent you from cloning a String
    > from an Object-pointer, but allows you to clone a String also from a
    > String-pointer.


    I don't have a reference in front of me but I believe that the return
    type is a part of the function signature. If that is the case, the
    overloaded version of clone will not act as a virtual method but rather
    overshadow the virtual method.

    Regards,

    Jon Trauntvein
    JH Trauntvein, Dec 5, 2006
    #8
  9. Pete Becker Guest

    JH Trauntvein wrote:
    >
    > I don't have a reference in front of me but I believe that the return
    > type is a part of the function signature. If that is the case, the
    > overloaded version of clone will not act as a virtual method but rather
    > overshadow the virtual method.
    >


    When the function in the base class returns a pointer or reference to a
    class type and the function in the derived class returns a pointer or
    reference, respectively, to a type derived from that type, the derived
    version still overrides the base version.

    --

    -- Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com)
    Author of "The Standard C++ Library Extensions: a Tutorial and
    Reference." (www.petebecker.com/tr1book)
    Pete Becker, Dec 5, 2006
    #9
  10. JH Trauntvein schrieb:
    > I don't have a reference in front of me but I believe that the return
    > type is a part of the function signature. If that is the case, the
    > overloaded version of clone will not act as a virtual method but rather
    > overshadow the virtual method.


    You can override a virtual member function and change its return type, but
    the new return type must be a derived class. It's called "Covariant Return
    Type".

    In Java, you can't (don't know if they introduced it in a newer version),
    so you have to downcast cloned Objects:

    String s = new String("some text");
    String cloned = s.clone(); // error, clone() returns Object!

    But you already _now_ here, that clone() returns a String, so casting would
    be superflous. With Covariant Return Types, you can let the compiler know
    that it's a String.

    --
    Thomas
    http://www.netmeister.org/news/learn2quote.html
    Thomas J. Gritzan, Dec 5, 2006
    #10
  11. On 2006-12-05 19:53, JH Trauntvein wrote:
    > wrote:
    >>
    >> Which means that you have something like this:
    >> struct Object {
    >> virtual Object* clone() {
    >> std::cout << "obj\n";
    >> return new Object(*this);
    >> }
    >> };
    >>
    >> struct String : public Object {
    >> int a;
    >> virtual String* clone() {
    >> std::cout << "str\n";
    >> return new String(*this);
    >> }
    >> };
    >>
    >> int main() {
    >> String* str = new String;
    >> Object* obj1 = str;
    >> Object* obj2 = obj1->clone();
    >> }
    >>
    >> As you see if you run the code it's the String::clone() function that
    >> is called, even tough you didn't know that it was a String. If you
    >> didn't use the String::clone() you would not have been able to create a
    >> clone since there is no 'a'-variable in Object, so when calling the
    >> copy-constructor of Object you get an Object and not a String. In other
    >> words, returning a String* does not prevent you from cloning a String
    >> from an Object-pointer, but allows you to clone a String also from a
    >> String-pointer.

    >
    > I don't have a reference in front of me but I believe that the return
    > type is a part of the function signature. If that is the case, the
    > overloaded version of clone will not act as a virtual method but rather
    > overshadow the virtual method.


    Small changes of the return type are allowed according to The C++
    Programming Language (12.2.6) and an example of using this with a clone-
    function can be found in 15.6.2. I'll refrain to quote the relevant
    parts since my copy is in Swedish and since the English->Swedish
    translation was not the best I'm afraid that any attempt by me to
    translate it back will remove whatever correctness is still there.

    --
    Erik Wikström
    =?ISO-8859-1?Q?Erik_Wikstr=F6m?=, Dec 5, 2006
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Guest

    Cloning Possible?

    Guest, Nov 10, 2003, in forum: ASP .Net
    Replies:
    1
    Views:
    398
    Steve C. Orr [MVP, MCSD]
    Nov 11, 2003
  2. =?Utf-8?B?QVZM?=

    cloning

    =?Utf-8?B?QVZM?=, Dec 14, 2004, in forum: ASP .Net
    Replies:
    3
    Views:
    492
    Eliyahu Goldin
    Dec 14, 2004
  3. Joel Leong

    Cloning ASPNET account

    Joel Leong, Jun 4, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    352
    Scott Allen
    Jun 4, 2005
  4. hitesh

    Cloning complex objects.

    hitesh, Apr 11, 2004, in forum: Java
    Replies:
    2
    Views:
    826
    Dmytro Sheyko
    Apr 15, 2004
  5. 7stud
    Replies:
    11
    Views:
    689
    Dennis Lee Bieber
    Mar 20, 2007
Loading...

Share This Page