Thread: Why use private?

  1. #1
    Registered User
    Join Date
    Nov 2008
    Posts
    127

    Why use private?

    I've been thinking about this recently. This question isn't specific to C++, but a general OO question. Why would you ever want to use private instead of protected? If you are the leaf node class, you don't lose any encapsulation and if you're a parent class, your children are going to want access to your members, otherwise a lot of the benefits of inheritance are lost. I can't think of any scenarios where a parent would want to restrict its childrens' access to its members.

  2. #2
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    protected members are accessible by a class's children, while private members are not. It provides an extra layer of abstraction.

    EDIT: What if you wanted to change one of the parent's member? You'd also had to change the code of ALL the derived classes that use it. To avoid such situation, private data and public interfaces are used extensively.
    Last edited by GReaper; 03-05-2012 at 02:32 PM.
    Devoted my life to programming...

  3. #3
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    If you are the leaf node class, you don't lose any encapsulation and if you're a parent class, your children are going to want access to your members, otherwise a lot of the benefits of inheritance are lost.
    O_o

    You have a couple of misunderstandings.

    First of all, "Final" classes are ......... Saying "It will never, ever be useful to further refine this class and its implementation." is retarded. With that in mind, you can't ever know that a class is truly a leaf of simply another branch. Thankfully, you can't even do "Leaf" classes in C++ without jumping through some serious "hoopage".

    Second, you can lose encapsulation by making a member protected instead of private. Consider an example: if every protected interface in `Base' is implemented to assume that member `mPointer' is never null and that member is not private a derived class may change that member to null breaking the implementation. By forcing derived objects to mutate `mPointer' through a protected interface `Base' can guarantee that `mPointer' is never null.

    Third, literally none of the benefits of inheritance are lost by making members or methods private if the interface is otherwise complete. It is only a matter of mutation by interface of mutation by overriding members and methods. For example, a derived class that needs to use `mPointer' may do so while `Base' manages the constraints that it requires if it provides an interface to do exactly that. Alternatively, if a derived class would only have used inherited privates to change the behavior of non-virtual functions that implies a problem in the chain of responsibility. Finally, an object is violating design principles if it would have only used inherited privates to store information unrelated to the base class interface and inherited implementation.

    Soma

  4. #4
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    C++11 now supports final classes.

  5. #5
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    And how unfortunate that it...

    Soma

  6. #6
    Registered User
    Join Date
    Nov 2008
    Posts
    127
    What if you wanted to change one of the parent's member?
    Refactor. Changing the base class will most likely mean you need to changed the derived class anyway.

    First of all, "Final" classes
    Who said anything about final classes?

    Saying "It will never, ever be useful to further refine this class and its implementation." is retarded.
    I agree. That's why private seems pointless.

    if every protected interface in `Base' is implemented to assume that member `mPointer' is never null and that member is not private a derived class may change that member to null breaking the implementation
    You should really be checking if a pointer is null before you use it. If it's never going to be null, then a reference should be used.

    Third, literally none of the benefits of inheritance are lost by making members or methods private if the interface is otherwise complete.
    I'd say it break the IS A relationship. If a base class can do X, the derived class should be able to as well. If you make X private, the derived class won't be able to anymore.

  7. #7
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Changing the base class will most likely mean you need to changed the derived class anyway.
    That's correct and exactly what the quote you are responding to said.

    Who said anything about final classes?
    You did by assuming that a specific class is a leaf instead of just another branch.

    I agree. That's why private seems pointless.
    Private facilities aren't subject to refinement as are protected and public facilities in normal branch classes; final classes, in whatever from, aren't subject to further refinement of at all. These are very different considerations. A private facility says "I (as in this class) expect this facility to be implemented in exactly this fashion for my interface but you can refine the interface and implementation independently.". A final class says "It will never be useful to refine this class.".

    You should really be checking if a pointer is null before you use it.
    Why? If higher level facilities guarantee a contract why should you verify it?

    I'm being totally serious here, why verify the validity of a contract when that responsibility lies elsewhere?

    Duplicating responsibilities is a good way to cause subtle bugs and trample performance.

    Sure, checking a single pointer for null is cheap, but apply that same logic to large modern file systems. Imagine how slow your system would be if the file system driver had to check ever node in the system for validity before requesting a new node for file expansion. It would cripple your system. Instead, the driver has functions that do the job of guaranteeing (as much as is possible with unreliable hardware) the validity of "free store" every "free store" operation so the expansion code can safely assume the "free store" is ready to go.

    If it's never going to be null, then a reference should be used.
    That's a good rule of them for function parameters but not so much for class data members.

    That aside, I can make a reference null. It is a violation of the C++ contract, but I can absolutely do it.

    Are you going to start checking that a reference isn't null just because I can be a dick?

    No. Of course you aren't. That would be foolish. You expect higher level facilities (in this case the C++ compiler) to do its job and the programmer to honor that contract.

    The situation I'm explaining is exactly the same; you expect the `Base' class implementation to hold to that contract so checking it is meaningless.

    If a base class can do X, the derived class should be able to as well.
    True. However, private facilities aren't subject to this logic because the goal of "OOP" is programming to an interface not an implementation. Privates facilities are not part of the interface. They are part of the implementation. Consider the interface `doSomethingAwesome': if the `Base' implementation of `doSomethingAwesome' is implemented in terms of the private method `doSomething' derived classes can still `doSomethingAwesome' by doing the same thing the base class does (inherited implementation) or do something entirely different (override implementation). The private method used to implement `doSomethingAwesome' doesn't break anything.

    If you make X private, the derived class won't be able to anymore.
    That situation can't, by the very definition, violate the "IS-A" relationship. The "IS-A" relationship is about object substitution by interface leaving assumptions, contracts, preconditions, postconditions, and so on intact. The private aspects of an object aren't part of the interface. They are only part of the implementation.

    Soma

  8. #8
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Quote Originally Posted by phantomotap View Post
    And how unfortunate that it...
    in a way, I agree, but I can see that it might be useful under some circumstances.

    in any case, simply making your destructor non-virtual is usually enough to make all but the most trivial derived classes act strangely.

    I personally don't understand why parts of the standard C++ library are effectively final, like std::string. it's not impossible to derive from it, but it's usually not advised, because it doesn't have a virtual destructor, or any virtual functions. lots of other stuff in the standard library can be subclassed, and I have always felt like std::string is missing some things that would be very useful, but if I want custom behavior, I have to make a whole new class, when it would be much easier to simply derive from it and add the things I want.

  9. #9
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    I know what you are saying, but that's not exactly the right way to look at it.

    You can derive from the standard classes; you just can't use them with inheritance based "OOP" in mind. You can derive and use them with other forms of "OOP".

    I have read the logs from the governing group and you probably wouldn't be satisfied with the rationale even if you read it. [Edit]The rationale simply isn't very good.[/Edit]

    Be one with the standard and accept. ^_^

    Soma

  10. #10
    Registered User
    Join Date
    Nov 2008
    Posts
    127
    Who said anything about final classes?
    You did by assuming that a specific class is a leaf instead of just another branch.
    I'm not sure why you would say a leaf class is final. Would you say that a leaf node could never become a branch? I said leaf because it has the least weight associated with it AFIAK. A leaf class simply means there is currently no class extending it. Nothing more.

    In your doSomethingAwesome example, wouldn't you prefer to have the flexibility to redefine the helper function?

  11. #11
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    A leaf class simply means there is currently no class extending it.
    That's true, but in framing your original question one of your assumptions was that a class didn't gain anything from private over protected semantics because it was a leaf class meaning that no class derived from it. You are, in making that one, also assuming that no class ever will derive from it making it final. The second a class does derive from that class the core of your assumptions (that nothing of semantic value from private is gained) vanishes.

    In other words, I brought up final because you query is framed assuming final.

    In your doSomethingAwesome example, wouldn't you prefer to have the flexibility to redefine the helper function?
    Why? Seriously, take a minute to answer that question. Provide an example, real code, to illustrate your point.

    Soma

  12. #12
    Registered User
    Join Date
    Nov 2008
    Posts
    127
    You are, in making that one, also assuming that no class ever will derive from it making it final.
    You're putting words in my mouth. I never said, nor insinuated, such a thing. Saying no class is currently derived from some class A does not make the assumption that no class ever will.

    Why? Seriously, take a minute to answer that question. Provide an example, real code, to illustrate your point.
    My view is probably too biased. Any example I come up with would probably result in you suggesting that the helper function shouldn't have ever been a helper function in the 1st place.

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by homer_3
    Any example I come up with would probably result in you suggesting that the helper function shouldn't have ever been a helper function in the 1st place.
    Or perhaps the non-virtual interface idiom could be used: the helper function could then be a private virtual member function, whereas doSomethingAwesome would be a non-virtual public member function.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Making something "private" is a vital part of the language.
    It would be a disaster if every method and variable of every class in the SC++L was public for example. Far too many people would mistakenly try and use many of the internals of a class that they were never meant to touch, and when the compiler libraries are later improved and updated, all hell would break loose for programs using the private things.
    It's not there to be unnecessarily restrictive, and its only used that way by people who don't know what they're doing, and don't know how to properly write usable classes.
    It's there to stop people doing stupid things and that is a very good thing indeed. Programmers need all they can to save them from themselves!
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  15. #15
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    The interface that a base class exposes to its children should be just as carefully designed as the interface it exposes to the rest of the world. The reason is that protected isn't really much more restrictive than public: there's still a potentially infinite amount of code that depends on it. (There is no limit on how many classes can derive from any given base, after all.)

    Therefore, saying that private is pointless and any derived class should have full access to its bases' internals is a recipe for disaster. I very rarely have protected members at all, and definitely no protected member variables. Member variables should either be subject to no constraints at all, and thus public (the rare case), or they should be private. Protected member functions are reserved for rather special cases, actually.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 04-10-2009, 02:20 AM
  2. private/public get/set
    By George2 in forum C# Programming
    Replies: 2
    Last Post: 05-04-2008, 12:49 AM
  3. The Private game 2
    By RoD in forum A Brief History of Cprogramming.com
    Replies: 4
    Last Post: 10-04-2002, 02:20 AM
  4. Why Private
    By Manitoadlet in forum C++ Programming
    Replies: 8
    Last Post: 09-16-2002, 08:18 AM