Thread: Inheritance operator overloading

  1. #1
    Registered User
    Join Date
    Oct 2004
    Posts
    24

    Inheritance operator overloading

    Hello,

    Thank you in advance for your time and help.

    I was hoping someone could clear some confusion up, over operator overloading and ineritance.

    If i have overloaded the << and the >> operators, for example to output an object of type Square, and then i have an object of type circle that inherits from the Square class - how can i ouput an object of type circle without retyping the overloaded operators to accept an object of type circle.

    e.g

    Code:
    friend istream& operator>>(istream&, Square&);
    friend ostream& operator<<(ostream&, const Square);
    and then i have a subclass (circle)...

    Code:
    friend istream& operator>>(istream&, Circle&);
    friend ostream& operator<<(ostream&, const Circle);
    I don't want to re-declare all of my overloaded operators.

    How is this achieved?

    I really appreiate some guidance in this area.

    Thank you for your time, help and advice.

    Best regards, global

  2. #2
    Registered User
    Join Date
    Aug 2003
    Posts
    470
    If you have a scheme like

    Code:
    class Base {
    public:
      
    private:
          virtual void put(std::ostream& os);
    };
    you can then allow derived classes to override put, thereby making operator<<'s call to put dispatch to the appropriate derived class's function.

  3. #3
    Registered User
    Join Date
    Oct 2004
    Posts
    24
    So what you're saying is, if i make my inital (super class) implementation of my overloaded operator functions - virtual functions - then i can still access them and use them?

    Also, the above doesn't allow you to alter what datatpye is returned - so it would be useless for the =, += , <<, >> operators.

    Thanks for the help.

    Regards, global
    Last edited by global; 12-20-2004 at 06:58 AM.

  4. #4
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    You would not need to alter the datatype returned. Keep your I/O handlers BASIC as possible! If you make it overly complex you may find it hard to override the function in one of the child classes.

  5. #5
    Registered User
    Join Date
    Oct 2004
    Posts
    24
    Thank you for your help, it is, as always, greatly received.

    So can i have what okinrus posted:
    Code:
    virtual void put(std::ostream& os);
    Because i thought you had to have:

    Code:
    friend istream& operator>>(istream&, Square3&);
    friend ostream& operator<<(ostream&, const Square3);
    ...and change it to Circle where appropriate, and write the whole function again.

    I have 2 classes that both have 3 constructors and both need to be outputed to the screen - but surely i don't have to write everything all over again? Is there a way to make my methods, virtual methods?

    If it's possible, i'll set about trying to do it - but i am not sure if it is yet.

    Thank you for taking the time to read my post.

    Best regards, gloabl

  6. #6
    Registered User
    Join Date
    Mar 2002
    Posts
    1,595
    You mean like this?
    Code:
    class shape
    {
      public:
       virtual void describe(){};
    };
     
    class square : public shape
    {
      public:
       void describe() {cout << side << endl;}
       int side;
       friend ostream & operator<<(ostream & os, square rhs) { os << rhs.side;}
    };
     
    class circle : public shape
    {
      public:
       void describe() {cout << radius << endl;}
       int radius;
       friend ostream & operator<<(ostream & os, circle rhs) { os << rhs.radius;}
    };
     
    int main()
    {
      square s;
      s.side = 4;
     
      circle c;
      c.radius = 3;
     
      shape * shapes[2];
      shapes[0] = &s;
      shapes[1] = &c;
     
      //using polymorphism to output to screen
      for(int i = 0; i < 2; ++i)
    	shapes[i]->describe();
     
      //overloading << operator to output to screen
      cout << s << endl;
      cout << c << endl;
     
    }

  7. #7
    Registered User jlou's Avatar
    Join Date
    Jul 2003
    Posts
    1,090
    More like this. Notice the virtual put method (as okinrus described) and how it does the work. Then notice how only one operator<< is required, because each derived class has its own put method that is automatically called because of polymorphism:
    Code:
    #include <iostream>
    
    class shape
    {
      public:
       virtual void put(std::ostream& os) const = 0;
       virtual ~shape() { }
    };
    
    std::ostream& operator<< (std::ostream& os, const shape& s)
    {
        s.put(os);
        return os;
    }
    
    class square : public shape
    {
      public:
       virtual void put(std::ostream& os) const {os << side << std::endl;}
       int side;
    };
     
    class circle : public shape
    {
      public:
       virtual void put(std::ostream& os) const {os << radius << std::endl;}
       int radius;
    };
    
    
    int main()
    {
      square s1;
      s1.side = 4;
     
      circle c1;
      c1.radius = 3;
     
      shape * shapes[2];
      shapes[0] = &s1;
      shapes[1] = &c1;
     
      //using polymorphism to output to screen
      for(int i = 0; i < 2; ++i)
        std::cout << *(shapes[i]);
     
      //overloading << operator to output to screen
      std::cout << s1;
      std::cout << c1;
    }

  8. #8
    Registered User
    Join Date
    Mar 2002
    Posts
    1,595
    Definitely cleaner. Thank you.

  9. #9
    Registered User
    Join Date
    Aug 2003
    Posts
    470
    So what you're saying is, if i make my inital (super class) implementation of my overloaded operator functions - virtual functions - then i can still access them and use them?
    No, operator<< and operator>> for stream output must be outside of the class. They are defined
    std:stream& operator<<(std:stream& os, const C& rhs). Hence, the ostream is in the left-hand-side position. By making these operators friends of the C class you're able to call the private put method. You can also make the put method public, in which case friends are unnecessary.

    Also, the above doesn't allow you to alter what datatpye is returned - so it would be useless for the =, += , <<, >> operators.
    Well, those operators may be defined virtually. But remember, you cannot simply change the type of the overided method to any old type. The type of the overrided method must be covariant to the superclass's method. The simple way of explaining this is that if your superclass's virtual method returns an abstract type, derived classes may return derived types of this abstract type. Your actual benefit here is limited, though. I've only found this technique to be useful in creating clone methods.
    Last edited by okinrus; 12-20-2004 at 07:08 PM.

  10. #10
    Registered User
    Join Date
    Oct 2004
    Posts
    24
    okinrus, jlou, elad - thank you all!

    Your help is very much appreciated, in what can be very trying times for someone trying to get their head around it all. I appreciate the time and effort (along with the clear examples) that you have given me.

    I have had a brief read through - but shall make myself some lunch and coffee and then sit down ready to get going.

    Just wanted to put in a quick 'thanks' now.

    Regards, global
    Last edited by global; 12-21-2004 at 07:05 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 06-08-2009, 03:03 PM
  2. Multiple Inheritance - Size of Classes?
    By Zeusbwr in forum C++ Programming
    Replies: 10
    Last Post: 11-26-2004, 09:04 AM
  3. inheritance and performance
    By kuhnmi in forum C++ Programming
    Replies: 5
    Last Post: 08-04-2004, 12:46 PM
  4. Inheritance and Polymorphism
    By bench386 in forum C++ Programming
    Replies: 2
    Last Post: 03-18-2004, 10:19 PM
  5. Inheritance vs Composition
    By Panopticon in forum C++ Programming
    Replies: 11
    Last Post: 01-20-2003, 04:41 AM