3

This code was written by Bruce Eckel in his book "Thinking in C++" Chapter 14 page 649. What I didn't understand was the comment he made below [emphasis added]:

The operator<< for Child is interesting because of the way that it calls the operator<< for the Parent within it : by casting the Child object to a Parent& (if you cast to a base-class object instead of a reference you will usually get undesirable results).

Here's the corresponding code:

#include <iostream>
using namespace std;

class Parent
{
    int i;

    public:

    Parent(int ii) : i(ii) { cout << "Parent(int ii)\n"; }
    Parent(const Parent& b) : i(b.i) { cout << "Parent(const Parent&)\n"; }
    Parent() : i(0) { cout << "Parent()\n"; }

    friend ostream& operator<<(ostream& os, const Parent& b) { 
        return os << "Parent: " << b.i << endl; 
    }
};

class Member
{
    int i;

    public:

    Member(int ii) : i(ii) { cout << "Member(int ii)\n"; }
    Member(const Member& m) : i(m.i) { cout << "Member(const Member&)\n"; }

    friend ostream& operator<<(ostream& os, const Member& m) { 
        return os << "Member: " << m.i << endl; 
    }
};

class Child : public Parent
{
    int i;
    Member m;

    public:

    Child(int ii) : Parent(ii), i(ii), m(ii) { cout << "Child(int ii)\n"; }

    friend ostream& operator<<(ostream& os, const Child& c) { 
        return os << (Parent&)c << c.m << "Child: " << c.i << endl; 
    }
};

int main()
{
    Child c(2);
    cout << "calling copy-constructor: " << endl;
    Child c2 = c;
    cout << "values in c2:\n" << c2;
}
moooeeeep
  • 31,622
  • 22
  • 98
  • 187
Plato
  • 33
  • 2

3 Answers3

1

Yes this is okay . Parent and Child are Polymorphic. as Child inherit's Client you can cast a Child& to Parent&

In expression os << (Parent&)c rhs (Parent&)c is of type Parent& So the operator<<(ostream& os, const Parent& b) will be called from operator<<(ostream& os, const Child& b)

In C++ Polymorphism only works when you have reference or Pointer type

Neel Basu
  • 12,638
  • 12
  • 82
  • 146
  • Though it's not repeated in the question, I think what the OP is asking is in the title: "What are those undesirable results?" ie., in the sentence from the book he quoted, what undesirable results will occur "if you cast to a base-class object instead of a reference". – WendiKidd Aug 18 '12 at 19:08
1

The undesirable result is that the compiler has to create a temporary copy of the Parent portion of the Child object, pass a reference to that temporary to the inserter, and then destroy the temporary. That's a lot of churning...

And, as @NeelBasu hinted, if Parent has virtual functions that are overridden in Child, calls to those functions from the inserter won't call the Child version, because the object passed in is a Parent object.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • Because that's what the cast says to do: `(Parent)whatever` creates a new object; `(Parent&)whatever` creates a reference to `whatever`. – Pete Becker Aug 18 '12 at 22:12
1

That's probably object slicing meant. That is, you'll lose some parts of your object by copying it into an instance of the parent class (instead of assigning a reference).

also have a look at the answers to this question:


Here's an example: (see http://ideone.com/qeZoa)

#include <iostream>
using namespace std;

struct parent {
  virtual const char* hi() const { return "I'm your father..."; }
};

struct child : public parent {
  const char* hi() const { return "No way!"; }
};

int main() {
  child c;
  cout << ((parent) c).hi() << endl;
  cout << ((parent&)c).hi() << endl;
}
Community
  • 1
  • 1
moooeeeep
  • 31,622
  • 22
  • 98
  • 187
  • I'm sorry, but in the book's example, there's no virtual function in the base class Child. – Plato Aug 18 '12 at 20:34
  • I mean, there's no virtual function in the base class Parent. – Plato Aug 18 '12 at 20:46
  • @Plato this is apparantly just one example for potentially undesirable side-effects resulting from this sort of casting. – moooeeeep Aug 18 '12 at 21:18
  • I'm just not sure if that was what the author meant to say. Note that the operator<<() function in Parent is not even a member function. It couldn't be virtual. – Plato Aug 18 '12 at 21:31
  • @Plato the author says _usually_ not _in this specific case_. But there may be more than this effect. – moooeeeep Aug 18 '12 at 21:44