Copy Inherited Objects

Discussion in 'C++' started by timid, May 17, 2008.

  1. timid

    timid Guest

    I'm attempting to learn how to use inheritance in C++, the following
    program should print the word 'Orange' on the screen but it prints
    'Apple' instead. Can someone explain what is wrong?

    #include <iostream>

    class Fruit
    {
    public:
    virtual const char* get_name() {return "(nothing)";}
    };

    class Apple: public Fruit
    {
    public:
    const char* get_name() {return "Apple";}
    };

    class Orange: public Fruit
    {
    const char* get_name() {return "Orange";}
    };

    int main()
    {
    std::cout << "Test inheritation" << std::endl;

    Fruit *myfruit1 = new Apple();
    Fruit *myfruit2 = new Orange();
    Fruit *myfruit3 = new Apple();

    std::cout << "myfruit1 = " << myfruit1->get_name() <<
    std::endl; // Prints "Apple"
    std::cout << "myfruit2 = " << myfruit2->get_name() <<
    std::endl; // Prints "Orange"
    std::cout << "myfruit3 = " << myfruit3->get_name() <<
    std::endl; // Prints "Apple"

    // The following does not work
    std::cout << "Now change myfruit3 from Apple to Orange..." <<
    std::endl;
    *myfruit3 = *myfruit2;

    // Prints "Apple" but should print "Orange"
    std::cout << "myfruit3 = " << myfruit3->get_name() << std::endl;

    // Wait for a keypress
    std::cin.get();

    delete myfruit1;
    delete myfruit2;
    delete myfruit3;
    }
     
    timid, May 17, 2008
    #1
    1. Advertising

  2. timid wrote:

    > #include <iostream>
    >
    > class Fruit
    > {
    > public:
    > virtual const char* get_name() {return "(nothing)";}


    Use std::string rather than char*.

    Also, a function such as "get_name" should usually be declared const.

    > };
    >
    > class Apple: public Fruit
    > {
    > public:
    > const char* get_name() {return "Apple";}
    > };
    >
    > class Orange: public Fruit
    > {
    > const char* get_name() {return "Orange";}
    > };
    >
    > int main()
    > {
    > std::cout << "Test inheritation" << std::endl;
    >
    > Fruit *myfruit1 = new Apple();
    > Fruit *myfruit2 = new Orange();
    > Fruit *myfruit3 = new Apple();
    >
    > [...]
    >
    > // The following does not work
    > std::cout << "Now change myfruit3 from Apple to Orange..." <<
    > std::endl;
    > *myfruit3 = *myfruit2;


    * derefences the pointer, yielding the object it's pointing to.
    Consequently, in your example you don't assign the _pointers_, you
    assign the _objects_ they are pointing to. That's a huge difference.
    Assigning an Orange to an Apple obviously does not do anything because
    you did not specify anything to happen in case of such an assignment.
    The invisible assignment operator automatically generated by the
    compiler is empty. In other words, the Apple is completely unaffected by
    the operation.


    If you want to assign a pointer to another pointer, you have to write:

    myfruit3 = myfruit2;

    However, in your program this would have disastrous results because you
    would lose the old value of myfruit3, which means you cannot delete your
    second Apple anymore. (You'd have to save the old value somewhere, for
    example in a temporary pointer variable.)

    What do you try to achieve by having myfruit3 point to a different object?


    --
    Christian Hackl
     
    Christian Hackl, May 17, 2008
    #2
    1. Advertising

  3. timid

    timid Guest

    On May 17, 10:49 pm, Christian Hackl <> wrote:
    > timid wrote:
    > > #include <iostream>

    >
    > > class Fruit
    > > {
    > > public:
    > > virtual const char* get_name() {return "(nothing)";}

    >
    > Use std::string rather than char*.
    >
    > Also, a function such as "get_name" should usually be declared const.
    >
    >
    >
    > > };

    >
    > > class Apple: public Fruit
    > > {
    > > public:
    > > const char* get_name() {return "Apple";}
    > > };

    >
    > > class Orange: public Fruit
    > > {
    > > const char* get_name() {return "Orange";}
    > > };

    >
    > > int main()
    > > {
    > > std::cout << "Test inheritation" << std::endl;

    >
    > > Fruit *myfruit1 = new Apple();
    > > Fruit *myfruit2 = new Orange();
    > > Fruit *myfruit3 = new Apple();

    >
    > > [...]

    >
    > > // The following does not work
    > > std::cout << "Now change myfruit3 from Apple to Orange..." <<
    > > std::endl;
    > > *myfruit3 = *myfruit2;

    >
    > * derefences the pointer, yielding the object it's pointing to.
    > Consequently, in your example you don't assign the _pointers_, you
    > assign the _objects_ they are pointing to. That's a huge difference.
    > Assigning an Orange to an Apple obviously does not do anything because
    > you did not specify anything to happen in case of such an assignment.
    > The invisible assignment operator automatically generated by the
    > compiler is empty. In other words, the Apple is completely unaffected by
    > the operation.
    >
    > If you want to assign a pointer to another pointer, you have to write:
    >
    > myfruit3 = myfruit2;
    >
    > However, in your program this would have disastrous results because you
    > would lose the old value of myfruit3, which means you cannot delete your
    > second Apple anymore. (You'd have to save the old value somewhere, for
    > example in a temporary pointer variable.)
    >
    > What do you try to achieve by having myfruit3 point to a different object?
    >
    > --
    > Christian Hackl


    Thank's for the help so far, it would appear that I need to learn a
    lot more.

    I'm going to try & rewrite this program so it'll work.
     
    timid, May 17, 2008
    #3
  4. Hi!

    Christian Hackl schrieb:
    >> class Fruit
    >> {
    >> public:
    >> virtual const char* get_name() {return "(nothing)";}

    >
    > Use std::string rather than char*.


    Normally I would agree, but in case of /const/ char* there is usually no
    problem. Only the use of char* for strings in C++ applications is nearly
    always a risk. On the other hand, using std::string for this (and
    similar) purposes is a significant runtime overhead. Only if you already
    have a std::string it is more advisable to return std::string, or if
    this causes no threading or aliasing problem const std::string&.

    > Also, a function such as "get_name" should usually be declared const.


    That's obviously true.


    > If you want to assign a pointer to another pointer, you have to write:
    >
    > myfruit3 = myfruit2;
    >
    > However, in your program this would have disastrous results because you
    > would lose the old value of myfruit3, which means you cannot delete your
    > second Apple anymore. (You'd have to save the old value somewhere, for
    > example in a temporary pointer variable.)
    >
    > What do you try to achieve by having myfruit3 point to a different object?


    I think the OP is seeking for something like a clone method.


    Marcel
     
    Marcel Müller, May 18, 2008
    #4
  5. timid

    James Kanze Guest

    On 17 mai, 23:11, timid <> wrote:
    > I'm attempting to learn how to use inheritance in C++, the
    > following program should print the word 'Orange' on the screen
    > but it prints 'Apple' instead. Can someone explain what is
    > wrong?


    > #include <iostream>


    > class Fruit
    > {
    > public:
    > virtual const char* get_name() {return "(nothing)";}
    > };


    > class Apple: public Fruit
    > {
    > public:
    > const char* get_name() {return "Apple";}
    > };


    > class Orange: public Fruit
    > {
    > const char* get_name() {return "Orange";}
    > };


    > int main()
    > {
    > std::cout << "Test inheritation" << std::endl;


    > Fruit *myfruit1 = new Apple();
    > Fruit *myfruit2 = new Orange();
    > Fruit *myfruit3 = new Apple();


    > std::cout << "myfruit1 = " << myfruit1->get_name() <<
    > std::endl; // Prints "Apple"
    > std::cout << "myfruit2 = " << myfruit2->get_name() <<
    > std::endl; // Prints "Orange"
    > std::cout << "myfruit3 = " << myfruit3->get_name() <<
    > std::endl; // Prints "Apple"


    > // The following does not work
    > std::cout << "Now change myfruit3 from Apple to Orange..." <<
    > std::endl;
    > *myfruit3 = *myfruit2;


    And what do you expect this to do? You cannot change the type
    of an existing object. In general, when inheritence is
    involved, you don't support assignment and copy.

    > // Prints "Apple" but should print "Orange"
    > std::cout << "myfruit3 = " << myfruit3->get_name() << std::endl;


    No. Should print "Apple". But a lot of typical implementations
    of the assignment operator (for more complicated types) will
    result in undefined behavior. The base class for an inheritence
    hierarchy should normally forbid assignment, so that the
    situation can't arrive, even accidentally.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, May 18, 2008
    #5
  6. timid

    James Kanze Guest

    On 18 mai, 11:29, Marcel Müller <> wrote:
    > I think the OP is seeking for something like a clone method.


    Or the letter/envelope idiom. Or perhaps just simply some
    information on OO design; he hasn't really expressed a concrete
    need for assignment.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, May 18, 2008
    #6
    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. Softari
    Replies:
    1
    Views:
    444
    John Harrison
    Jul 14, 2004
  2. Alex
    Replies:
    2
    Views:
    1,291
  3. rdc02271
    Replies:
    24
    Views:
    772
    Jacek Dziedzic
    Dec 27, 2005
  4. Replies:
    26
    Views:
    2,180
    Roland Pibinger
    Sep 1, 2006
  5. 7stud --
    Replies:
    11
    Views:
    468
    7stud --
    Nov 9, 2007
Loading...

Share This Page