CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 24
  1. #1
    Join Date
    Mar 2003
    Location
    Germany, K-Town
    Posts
    578

    setter and getter vs. public members

    This is kinda related to my other thread about protected members.

    If I have a data member, maybe an int val which should be readable as well as writable by clients. Is it still better practice to create a getter AND setter method instead of making the member public?
    - Matthias

    "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup

  2. #2
    Join Date
    Mar 2004
    Location
    Israel
    Posts
    638
    If an object is fully accessible to anyone anywhere, then what is the point
    of initialization during construction?...
    Using a public member is using a global (in terms of accessibility) which
    collides C++ encapsulation.
    **** **** **** **** **/**

  3. #3
    Join Date
    Mar 2003
    Location
    Germany, K-Town
    Posts
    578
    I don't get your point. It's not global, it's still in the context of the class.
    - Matthias

    "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup

  4. #4
    Join Date
    Mar 2004
    Location
    Israel
    Posts
    638
    An object instance allows everyone to "mess" its public member, like a program that allows everyone to "mess" its globals.
    **** **** **** **** **/**

  5. #5
    Join Date
    Feb 2002
    Posts
    4,640
    Guysl's point is that it's globally accessable, i.e. accessable by anyone in the (program) world. The problem with this approach is that the class itself then has no way of knowing that someone has changed it's variable(s) which can lead to disaster. I believe that there was an example posted, something like this:
    Code:
    class foo
    {
      public:
        foo() { m_MyData = new char [100]; }
        ~foo() { delete [] m_MyData; }
    
        void doSomethingWithData(const char *pNewData)
         {  strcpy(m_MyData, pNewData); }
    
        char *m_MyData;
    };
    
    int main()
    {
      foo myFoo;
      myFoo.m_MyData = NULL;
      myFoo.doSomethingWithData("This will crash!!!");
    }
    This is bad. Since it's my data, I'm assuming that the data will be valid for the life of the class instance. However, because the data is public, anyone can change it, and cause crashes, memory leaks, etc...

    Now, if the data was private, then only my class can change it. Therefore, I can completely control when it's created/deleted, etc.

    Viggy

  6. #6
    Join Date
    Aug 2000
    Location
    New York, NY, USA
    Posts
    5,656
    Public setter and getter (for a private member), compared to a public member variable, are similar in access rights, but have a significant difference: setter (and getter) provide extra layer of abstraction.
    A few of the benefits are:
    - controlled access (optional validation, counters, etc.)
    - notification of a change (obviously), so you can update related data
    - hiding implementation details (you can change a type of that member, or even combine it with another or split into multiple members), without changing client's code
    Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
    Convenience and productivity tools for Microsoft Visual Studio:
    FeinWindows - replacement windows manager for Visual Studio, and more...

  7. #7
    Join Date
    Oct 2000
    Location
    London, England
    Posts
    4,773
    It's a matter of style. When they implemented std::pair they made it a struct (which is the same as a class anyway). So you use aPair.first and aPair.second to access rather than aPair.getFirst() and aPair.getSecond().

    Generally the rule is that for small data structs it is fine to use public members, usually fairly basic types, but for fully-fledged classes it's slightly more conventional to make the attributes private and use access functions.

    While in C++ a class and a struct are the same thing, on a design level, I would call a struct a collection of data - it may have user-defined constructors but not really "methods" as such. A class has attributes rather than data and methods.

    get functions are usually inlined and therefore there is no major difference in performance. set functions can be useful for debugging as you can stick a breakpoint or a cout in a set function to trace where it is being called more easily.

  8. #8
    Join Date
    Mar 2003
    Location
    Germany, K-Town
    Posts
    578
    Alright, thanks, I usually do it like NMTop40 said. Although struct is pretty useless in C++ I use it when I have a small class which has no user defined methods and only data members which are supposed to be accessed by the "public domain"

    And what if I have a class (a nested class for example) that I don't want *everyone* to access a certain setter method, but only the outer class. Then 'friend' and 'private' are the way to go instead of just making the setter public, right?
    - Matthias

    "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup

  9. #9
    Join Date
    Oct 2000
    Location
    London, England
    Posts
    4,773
    With a nested class I will sometimes put the nested class in the private area of the class but make its access all public, thus giving the outer class full access.

  10. #10
    Join Date
    May 2000
    Location
    KY, USA
    Posts
    18,652
    Quote Originally Posted by NMTop40
    While in C++ a class and a struct are the same thing...
    Well...in general this is correct, however, there are two differences between them...
    • By default, the members of a class are private, while the members of a structure are public.
    • Structs are inherited from publically by default while classes are inherited from privately.

    Aside from these distinctions, structures and classes perform exactly the same function.

  11. #11
    Join Date
    Oct 2000
    Location
    London, England
    Posts
    4,773
    Yes that is true. I generally think in a class it is clearer to use the keyword "private" anyway though.

  12. #12
    Join Date
    Apr 2004
    Location
    In the back seat of New Horizons.
    Posts
    1,238
    One thing that could come in handy is the use of a friend function. This could help you get what you want.
    Here are the rules, you must obey them or the gender bender will get you.

    And if you ever think of posting without code-tags, the evil monkey will come after you.

  13. #13
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470
    Friends are iffy in that they greatly increase the coupling in your program, which is something that you generally want to reduce. Indeed, friendship is the tightest coupling there is, followed by inheritance (because friendship grants access to all members, whereas inheritance still denies access to private members).

    The thing to keep in mind is the distinction between interface and implementation. A well-designed class will present a good, useful interface to the rest of the world. The implementation of that interface, however, should be hidden. The rest of the program should not be interested in how the class works, only in what it does. By hiding the implementation, you give yourself the freedom to change that implementation at will without affecting the rest of the program. Expose any part of your implementation and you have to be very careful about changing it, because other classes and functions may be dependent on the specifics (IOW, you have high coupling between classes).

    Implementation hiding reaches its peak with the pimpl idiom, where the class consists only of public function members and a single pointer to an implementation class:
    Code:
    class foo
    {
    public:
        // function members
    
    private:
        class fooimpl* pimpl;
    };
    Using this idiom, the entire implementation is hidden away in the implementation file. The outside world only sees a single name (fooimpl), without even a class definition - and even the little bit that can be "seen" is private. The freedom this gives you to radically alter the implementation is unrivalled - you cannot affect anyone else, even if you completely rewrite the implementation. And, since changing the implementation doesn't even affect the header file, a complete rewrite of the implementation still only requires the recompilation of a single file. (Of course, if the new implementation is rubbish, that is a sort of effect, but that's not what I mean.)

    The protected section of a class is there to provide an interface for use by derived classes only - it's like the public section apart from restricted access.

    This is not about style, this is about clean code, maintainable code, robust code - code that you can muck about with without having the whole edifice collapse around your ears; code that you're not afraid to make improvements to, because you know changes will be localised and easily undone.

    My personal approach to the implementation of a class's (public and protected) interface is:

    1) Whenever possible, make it invisible (using pimpl).
    2) If I can't make it invisible, make it private.
    3) If I can't make it private, retire, because I've forgotten how to write C++.

    Your mileage may vary, of course. I've described a personal approach, one which comes from viewing C++ classes not as blobs that contain functions and data, but as entities that provide an interface and an implementation of that interface. To my mind, data members are implementation, with very few exceptions (I can't think of one at the moment), so should be hidden from everyone.
    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


  14. #14
    Join Date
    Apr 2004
    Location
    In the back seat of New Horizons.
    Posts
    1,238
    Quote Originally Posted by Graham
    Friends are iffy in that they greatly increase the coupling in your program, which is something that you generally want to reduce. Indeed, friendship is the tightest coupling there is, followed by inheritance (because friendship grants access to all members, whereas inheritance still denies access to private members).

    The thing to keep in mind is the distinction between interface and implementation. A well-designed class will present a good, useful interface to the rest of the world. The implementation of that interface, however, should be hidden. The rest of the program should not be interested in how the class works, only in what it does. By hiding the implementation, you give yourself the freedom to change that implementation at will without affecting the rest of the program. Expose any part of your implementation and you have to be very careful about changing it, because other classes and functions may be dependent on the specifics (IOW, you have high coupling between classes).

    Implementation hiding reaches its peak with the pimpl idiom, where the class consists only of public function members and a single pointer to an implementation class:
    Code:
    class foo
    {
    public:
        // function members
    
    private:
        class fooimpl* pimpl;
    };
    Using this idiom, the entire implementation is hidden away in the implementation file. The outside world only sees a single name (fooimpl), without even a class definition - and even the little bit that can be "seen" is private. The freedom this gives you to radically alter the implementation is unrivalled - you cannot affect anyone else, even if you completely rewrite the implementation. And, since changing the implementation doesn't even affect the header file, a complete rewrite of the implementation still only requires the recompilation of a single file. (Of course, if the new implementation is rubbish, that is a sort of effect, but that's not what I mean.)

    The protected section of a class is there to provide an interface for use by derived classes only - it's like the public section apart from restricted access.

    This is not about style, this is about clean code, maintainable code, robust code - code that you can muck about with without having the whole edifice collapse around your ears; code that you're not afraid to make improvements to, because you know changes will be localised and easily undone.

    My personal approach to the implementation of a class's (public and protected) interface is:

    1) Whenever possible, make it invisible (using pimpl).
    2) If I can't make it invisible, make it private.
    3) If I can't make it private, retire, because I've forgotten how to write C++.

    Your mileage may vary, of course. I've described a personal approach, one which comes from viewing C++ classes not as blobs that contain functions and data, but as entities that provide an interface and an implementation of that interface. To my mind, data members are implementation, with very few exceptions (I can't think of one at the moment), so should be hidden from everyone.
    Well, yes, you're right. I should have stated that friend functions/classes have to be dealt with care. But it is one example on how the program can get access to a class's variables or functions.
    Here are the rules, you must obey them or the gender bender will get you.

    And if you ever think of posting without code-tags, the evil monkey will come after you.

  15. #15
    Join Date
    Apr 2004
    Location
    In the back seat of New Horizons.
    Posts
    1,238
    Graham, I've read your entire post, but I still have some questions.

    When you talk about the pimpl idiom, do you mean something like having 2 classes, one for implementation and one that uses the implementation class but prevents the modification of this class?
    Last edited by YourSurrogateGod; July 22nd, 2004 at 05:04 AM.
    Here are the rules, you must obey them or the gender bender will get you.

    And if you ever think of posting without code-tags, the evil monkey will come after you.

Page 1 of 2 12 LastLast

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