A class that uses another class's objects

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • VanKha
    New Member
    • May 2007
    • 21

    A class that uses another class's objects

    After reading some books in c++,I know that it is better to hide the data members ,but sometimes the rule makes everything messy and terrible ! For example
    Code:
    class Node{
    private:
        int key;
        Node *left;
        Node *right;
    pubic:
      // I have to provide a lot of method so that other class can deal with the node!!!
        Node();
        int getKey();
        void setKey();
        Node *getLeft();
        Node *getRight();
        //...
    };
    class Tree{
    private:
       Node *root;
    public://...
    };
    The annoying thing here is that,in Tree's method,if I want to use the key of left of a Node *node, I must write: node->getLeft()->getKey() !!! Omg !!!

    I also think of the alternative that just write the class Tree only, but if so, how can we use the root ?(Because we programming with new and delete,it is better to deal all with pointers,isn't it ?And if we declare
    Code:
    class Tree{
      int key;
      Tree* left;
      Tree* right;
    //...
    };
    so in the methods,we can only use THIS to refer to the root . But this->...=... is not allowed ! That's another problem !
    Please help me .
    _______________ _
    Regards
  • ravenspoint
    New Member
    • Jul 2007
    • 111

    #2
    Oh boy! Here we go!

    IMHO, despite what the textbooks say, I prefer to keep attributes public unless they are interdependant or potentially invalid. If there are combinations of attributes that are invalid, then this needs to be checked inside set methods, whose use is enforced by making the involved attributes private.

    If all values, and all combinations, of attributes are valid, then save yourself a lot of typing by making them public.

    Comment

    • seforo
      New Member
      • Nov 2006
      • 60

      #3
      You rather use structs and then define some functions to work on the members of struct other than declare data members of the class as public. If you declare data members of the class public, you are destroying the concept of data encapsulation.

      Comment

      • ravenspoint
        New Member
        • Jul 2007
        • 111

        #4
        seforo is correct - a class is just a fancy term for a struct, with a few extra bells and whistles. Sometimes, though, the bells and whistles are useful, so it is many years since I used a struct where a class works.

        As for "destroying the concept of data encapsulation", well, as a practical coder, if such a terrible sin saves me some typing, then I will have to be a sinner.

        Comment

        • weaknessforcats
          Recognized Expert Expert
          • Mar 2007
          • 9214

          #5
          Originally posted by ravenspoint
          As for "destroying the concept of data encapsulation", well, as a practical coder, if such a terrible sin saves me some typing, then I will have to be a sinner.
          It's not the saving of typing that's important. It's the hiding of the implementation.

          By not hiding the implementation (like using public data members) you cause the users to encode your member names in their applications. Now it you need to redesign your class (or struct) the users will need to change their code. With a large user base, you will be prevented from making your change. Your product dies at this point.

          It is essential to keep ripple at a minimum. If you don't do this, the object design cycle (analyze, design, code) is not possible. You need working objects that stay working through repeated redesign cycles with no impact on users.

          Case in point: A Date class that has integers for month, day and year. The users have the data names for month, day and year in their code. Now the management decides to use a CIM date (yyyymmddhhmiss nnnn). Unfortumately, installing this from of Date will require modification of user code. A small change has now become a big change.

          However, the saving of typing is significant. It's lazy.

          Comment

          • ravenspoint
            New Member
            • Jul 2007
            • 111

            #6
            Originally posted by weaknessforcats
            It's not the saving of typing that's important. It's the hiding of the implementation.

            By not hiding the implementation (like using public data members) you cause the users to encode your member names in their applications. Now it you need to redesign your class (or struct) the users will need to change their code. With a large user base, you will be prevented from making your change. Your product dies at this point.

            It is essential to keep ripple at a minimum. If you don't do this, the object design cycle (analyze, design, code) is not possible. You need working objects that stay working through repeated redesign cycles with no impact on users.

            Case in point: A Date class that has integers for month, day and year. The users have the data names for month, day and year in their code. Now the management decides to use a CIM date (yyyymmddhhmiss nnnn). Unfortumately, installing this from of Date will require modification of user code. A small change has now become a big change.

            However, the saving of typing is significant. It's lazy.

            weaknessforcats is correct, if you are creating libraries for other coders to use. Very few people, in reality, do this. If you are writing for yourself, and you change the design, then it is a simple matter to refactor, with the compiler pointing out where changes are needed.

            Saving typing is not JUST lazy. It can also mean the difference between profit and loss on a coding contract, won against coders in low-wage economies all around the world. A successful coder needs to know how to produce reliable code, fast. He does not need to worry about hiding the implementation and breaking the concept of encapsulation.

            Comment

            • ravenspoint
              New Member
              • Jul 2007
              • 111

              #7
              Let me state my position more fully.

              The 'private' keyword strikes me as nonsensical. It does not make the attribute private in any meaningful sense, all it does is enforce the use of accessor methods. If all your accessor methods look like this

              [CODE=cpp]setAttribute1( int i ) { myAttribute1 = i; }
              int getAttribute( ) { return myAttribute1; }
              [/CODE]
              then you are wasting your time - the compiler is going to optimize away your typing anyway.

              Now, weaknessforcats is correct: if you are providing a library for other's to use in their code, it is important to hide your implementation from them. Unfortunately, private does no such thing. You will still receive endless grief when some yahoo edits, and breaks, your code then reports a bug.

              This, among other conveniences, is why you use COM to expose your methods.

              Comment

              • weaknessforcats
                Recognized Expert Expert
                • Mar 2007
                • 9214

                #8
                Originally posted by ravenspoint
                Saving typing is not JUST lazy. It can also mean the difference between profit and loss on a coding contract, won against coders in low-wage economies all around the world. A successful coder needs to know how to produce reliable code, fast. He does not need to worry about hiding the implementation and breaking the concept of encapsulation.
                This is great. I actually made a good living doing things just this way. At the time (1965-1990) my phrase for it was: Gee, the guy that coded this thing must have been a chimpanzee. But do not fear. Let me rewrite you application correctly, and all of your bugs will go away.

                Then I rewrote the application using my own style causing the next guy to throw it away and start over.

                Throw-away code os OK for applications you can hold in your head or have limited distribution (like the computer is in the basement and the users on on the second floor). But in any real, modern, application, you cannot afford to recode every time. Even if the thing is slower, reuse trumps recode every time.

                You code for reuse.

                Originally posted by ravenpoint
                The 'private' keyword strikes me as nonsensical. It does not make the attribute private in any meaningful sense, all it does is enforce the use of accessor methods. If all your accessor methods look like this
                That is not the point of private inheritance. Private inheritance (also called implementation inheritance) occurs when you want the implementation of the class but do not want the class interface. Accessor functions are not mandated. It's almost the same as HAS-A where the class is represented by a private object.

                Originally posted by ravenspoint
                This, among other conveniences, is why you use COM to expose your methods.
                COM fails to separate the interface from the implementation. COM was developed intiailly in C and ported to C++ when it was still fashionable to use public virtual functions. Check out the design pattern called Template Method so see how (and why) you separate your interface from your implementation.

                Also, COM does not work in Unix or Linux.

                Comment

                • ravenspoint
                  New Member
                  • Jul 2007
                  • 111

                  #9
                  "That is not the point of private inheritance."

                  I do not believe we were talking about private inheritance. We were talking about private attributes.

                  I know very little about private inheritance. I find that I rarely use inheritance in real work. It looks great in textbooks, I suppose, but is hardly ever necessary to solve a problem.

                  As for re-use, well copy and paste does the job for me :-)

                  Comment

                  • weaknessforcats
                    Recognized Expert Expert
                    • Mar 2007
                    • 9214

                    #10
                    Originally posted by ravenspoint
                    I do not believe we were talking about private inheritance. We were talking about private attributes.
                    I'm guessing you don't hard-code numbers in your programs. I'm guessing you use macros instead.

                    #define MAX 10

                    and have 10,000 occurances of MAX rather than 10,000 hard-coded 10's.

                    A public arttribute is the same as hard-coding a 10.

                    You want a function MyClass::MAX() that returns the current max value. The current max value is private. The MyClass::MAX() is public.

                    Comment

                    • ravenspoint
                      New Member
                      • Jul 2007
                      • 111

                      #11
                      Originally posted by weaknessforcats
                      I'm guessing you don't hard-code numbers in your programs. I'm guessing you use macros instead.

                      #define MAX 10

                      and have 10,000 occurances of MAX rather than 10,000 hard-coded 10's.

                      A public arttribute is the same as hard-coding a 10.

                      You want a function MyClass::MAX() that returns the current max value. The current max value is private. The MyClass::MAX() is public.
                      I disagree.

                      Using the define helps to disambiguate ( is that 10 the base of the number system or the maximum array dimension or some other 10 used for some other reason? A search is going to overwhelm with many different uses of 10, MAX will, hopefully, be used for just one thing.)

                      MyClass::MAX() as opposed theclass.max does not have this advantage and is a pain for something that will be optimized away.

                      Comment

                      • weaknessforcats
                        Recognized Expert Expert
                        • Mar 2007
                        • 9214

                        #12
                        Originally posted by ravenspoint
                        MyClass::MAX() as opposed theclass.max does not have this advantage and is a pain for something that will be optimized away.
                        There are asumptions here:
                        1) that max is a class member
                        2) that MyClass::MAX() will be optrimized away. It may have to get the current max from a registry somewhere rather than some simple return.
                        3) that the future can be foretold. That is, if max is a public class member, and is used in 10,000 places, that you will never need to get the current max value from a registry. If you have to, you will need to make 10,000 changes instead of changing MyClass::MAX(), recompiling one file and re-linking.

                        Comment

                        • ravenspoint
                          New Member
                          • Jul 2007
                          • 111

                          #13
                          Originally posted by weaknessforcats
                          There are asumptions here:
                          1) that max is a class member
                          2) that MyClass::MAX() will be optrimized away. It may have to get the current max from a registry somewhere rather than some simple return.
                          3) that the future can be foretold. That is, if max is a public class member, and is used in 10,000 places, that you will never need to get the current max value from a registry. If you have to, you will need to make 10,000 changes instead of changing MyClass::MAX(), recompiling one file and re-linking.
                          1) I have already explicitly made this assumption. Read earliest posts

                          2) ditto

                          3) global search and replace is your friend.

                          Me, I think that you are making a very strange assumption. You are prepared to do a lot of work now, every day, just on the off-chance that a low probability event might cause extra work some day in the future. Perhaps you are paid by the hour?

                          Comment

                          • JosAH
                            Recognized Expert MVP
                            • Mar 2007
                            • 11453

                            #14
                            Originally posted by ravenspointMe, I think that you are making a very strange assumption. You are prepared to do a lot of work now, every day, just on the off-chance that a low probability event [B
                            might [/B]cause extra work some day in the future. Perhaps you are paid by the hour?
                            I'm with WeaknessForCats here: there's a huge difference between scientific
                            and/or industrial strength software and home brew one-man cleverness. The off-
                            chance occasions are not so rare according to Murphy and low probability
                            events show up sooner than you want them. You obviously have never been
                            there which doesn't matter but please don't blame me when you hit it.

                            kind regards,

                            Jos

                            Comment

                            • Banfa
                              Recognized Expert Expert
                              • Feb 2006
                              • 9067

                              #15
                              Originally posted by ravenspoint
                              3) global search and replace is your friend.
                              Actually "only having to change the code in 1 place" is your friend, a global search and replace is asking for trouble and time spent debugging and fixing compiler errors.

                              In fact I would have thought that it is self-evident that the more code changes you perform the more likely you are to introduce a bug to the code.

                              I too am with WeaknessforCats on this. The class should expose an interface and keep it's data hidden it is more defensive, and you maintain a better control of what is going on.

                              Your argument of time wasted typing extra characters is a particularly poor one, in my experience the time spent typing is far outweighed by the time spent thinking, designing, testing and maintaining.

                              Data encapsulation makes both testing and maintaining easier and quicker.

                              Comment

                              Working...