CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7
  1. #1
    Join Date
    Jul 2000
    Location
    CT
    Posts
    10

    Question overloading operator >>

    I am having trouble overloading operator >>. I can overload operator << with no problem but the reverse is giving me difficulty - perhaps I am missing something.

    Here's some sample code.

    class c2
    {
    public:
    short i;
    double d;
    .... other members - different from class c1
    c2();
    ~c2();
    }


    class c1
    {
    int i;
    double d
    ... // other members
    public:
    c1& operator<<(const c2& p) { return *this;} // this compiles
    c2& operator>>(const c1& p) {..} // this won't compile

    In operator << I want to populate a c1 object with members from c2.

    In operator >> I want to populate a c2 object with members from c1.

    Any ideas - please help. I can't find a good example in any texts.

    Thanks.
    JB

  2. #2
    Join Date
    Aug 1999
    Posts
    74
    what error are you getting ? post that.

    Also you don't have a ; to end class c2 .. is this a typo ?

  3. #3
    Join Date
    Jul 2000
    Location
    CT
    Posts
    10

    fixed

    Thanks for the reply. I had the syntax wrong.

    operator>> should be:
    c2& operator>>(const c2& p)
    {
    return p;
    }

  4. #4
    Join Date
    May 2000
    Location
    Birmingham, England
    Posts
    213
    I think there's another error in your code, logical rather than syntatic

    --In operator << I want to populate a c1 object with members from c2.

    --In operator >> I want to populate a c2 object with members from c1.

    The implication of the code in your post is

    c1 x;
    c1 y;
    c2 z;

    x << z; // You get what you want
    z = x >> y; // I don't think you want this

    To get the behaviour you seem to want, you would need to put the
    >> operator into the c2 class. It has to be this way in order for
    c2 to be on the LHS. the other option is to do it outside of either
    class.e.g
    c2 &operator>>(c2 &x, c1 &y){...}
    c1 &operator<<(c1 &x, c2 &y){...}

  5. #5
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470
    In an earlier thread on this subject, I suggested that using operators >> and << was probably not a good idea. I think the fact that there is so much confusion about what needs to be declared, and how to declare it tends to back up my point. the problem arises because there is no secure mental mapping of those operators to the task assigned to them, so you're constantly having to remind yourself of what is supposed to be happening. Replace them with named member functions like "SupplyTransferData" and "ReceiveTransferData" and at least you now know what each function is supposed to do. Than, if you absolutely insist on implementing the operators, you can at least implement them as free functions using those member functions:
    Code:
    class A
    {
    public:
        struct AData
        {
             // Data to be transferred
        };
        AData SupplyTransferData();
    };
    
    class B
    {
    public:
        void ReceiveTransferData(const A::AData&);
    };
    
    B& operator<<(B& b, const A& a)
    {
        b.ReceiveTransferData(a.SupplyTransferData());
        return b;
    }
    The "AData" struct is only an illustration, but you get the idea.

    Mind you, if you do carry on with using << and >> in this way, I just hope that I'm never the one to have to pick up and maintain your code.
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
    --
    Sutter and Alexandrescu, C++ Coding Standards

    Programs must be written for people to read, and only incidentally for machines to execute.

    --
    Harold Abelson and Gerald Jay Sussman

    The cheapest, fastest and most reliable components of a computer system are those that aren't there.
    -- Gordon Bell


  6. #6
    Join Date
    Jul 2000
    Location
    CT
    Posts
    10

    operator>>

    Thanks for all of the input. The extent to which I am using these operators is minimal - one call. My classes have a lot of members and using functions is a good idea - which I've done. I like the flexibility if the operator. Plus, the operators are self-explanatory *a >> *b - load a to b
    *a << *b - load b to a.

    If this isn't easy to follow, then I hope this code never crosses the pond.


    Thanks again for your help. If I do get a lot of complaints about this, from my compadres, I will implement functions.

    JB

  7. #7
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470
    I'm not trying to be offensive about this, honestly. I just think that using an operator to do a job that is done more clearly by a function call tends to obscure code, and we should always strive for clarity. I have to say that I disagree that "a >> b" is self-explanatory. Seeing that in isolation, my first guesses would be that either a and b are integral and it's shifting bits, or that a is derived from istream and it's reading the value of b. Also, you have potentially two ways of doing the same thing: "a >> b" and "b << a". Is it obvious that these two are identical? Why should they be?

    Another factor is that, by doing it this way, you're introducing a strong coupling between the two classes, and another good guideline is "low coupling, high coherence" - that is, always take the design that reduces coupling. If we modify my previous suggestion and encapsulate the transferred data into a separate class (or struct), then we can eliminate the coupling entirely:
    Code:
    // CommonData.h
    struct CommonData
    {
        // whatever
    };
    
    // A.h
    #include "CommonData.h"
    
    class A
    {
    public:
        CommonData SupplyData() const;
        void ReceiveData(const CommonData&);
        // etc.
    };
    
    // B.h
    #include "CommonData.h"
    
    class B
    {
    public:
        CommonData SupplyData() const;
        void ReceiveData(const CommonData&);
        // etc.
    };
    With this structure, classes A and B have no dependency on each other, you're not stuck with forward declarations or the need to artificially introduce pointers (to avoid the need for a complete class declaration). You can also easily introduce class C (also transferring CommonData) into the scheme. Serialisation is also simple because, by providing the member functions, you have a ready-made way to consistently serialise the common data. And consider also that, if you do decide you want to serialise these classes, you're going to have another set of operator << and >> to deal with doing a different job to the original.

    Just because it's only used once now, doesn't mean that there won't be a great demand for it in the future. Also, why expend all this effort on something that's only used once?

    I went down this road of defining operators to do (inappropriate)things "because I could" many years ago. I wouldn't do it again, because I have been in the situation of picking up code like that - I hated it and resolved that I wouldn't do it again and potentially put someone else through it.

    Why not implement operator=() ?
    Code:
    //B.h (others as before)
    #include "CommonData.h"
    class B
    {
    public:
        CommonData SupplyData() const;
        void ReceiveData(const CommonData&);
        B& operator=(const CommonData& cd)
        {
            ReceiveData(cd);
            return *this;
        }
        // etc.
    };
    
    // main.c
    #include "A.h"
    #include "B.h"
    
    int main()
    {
        A a;
        B b;
    
    // do stuff...
    
        b = a.SupplyData();
    }
    I don't think that's as clear as "b.ReceiveData(a.SupplyData());", but I do think it's a bit clearer than "b << a" or "a >> b".

    As a final alternative, you could replace the "Supply" and "Receive" functions with simple accessors:
    Code:
    struct CommonData
    {
        // whatever
        CommonData& operator=(const CommonData&);
    };
    
    class A
    {
    public:
        const CommonData& CommonStuff() const;
        CommonData& CommonStuff();
    };
    // Ditto for class B.
        
    int main()
    {
        A a;
        B b;
    
        // do stuff
    
        b.Commonstuff() = a.CommonStuff();
    };
    Now that's expressive (and extendable).

    Like I say, I'm not trying to be insulting or anything, I'm just trying to pass on the lessons of personal experience.
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
    --
    Sutter and Alexandrescu, C++ Coding Standards

    Programs must be written for people to read, and only incidentally for machines to execute.

    --
    Harold Abelson and Gerald Jay Sussman

    The cheapest, fastest and most reliable components of a computer system are those that aren't there.
    -- Gordon Bell


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured