Accessing private data members directly or using another private method?

Or is it better use another private utility method to access private data members rather than directly accessing the variables? Just wondering if it's one of those things that you shouldn't do, or if it doesn't matter because the variables are private.

Edit: Just wanted to clarify. I'm talking about accessing the variables directly through a private utility method.
Last edited on
You can only access private members from member functions. If you want to access them from another scope, write a public method. If you want to access from a method, you can do it directly.

Overall, I don't see much point in using private members. They are only there to make things cleaner, and don't have any impact on runtime. They are good when you're working on a big app, together with many other people. However they are quite useless otherwise and only make things more complicated.
closed account (1yR4jE8b)
The whole point of private variables is abstraction. If I write a class, I want my class to just DO something, I don't want the users to have to worry about what's going on behind the scenes. The more access they have to that the more chances they'll mess something up. It's definitely not pointless to protect critical sections of code through private access. If you think you need to make a private variable public, then you need to rethink what you are trying to achieve with what you are doing and possibly rethink your entire design.

In general, mutator methods should be avoided but they DO have their place. I just try to avoid them in general.
Overall, I don't see much point in using private members.


Encapsulation.

A properly encapsulated class is impossible (or at least extremely difficult) to misuse.

Take std::string for example. It has a member to record the length, and a member which is a pointer to the string buffer, but you can't access them directly. If the user (you) had access to those members, it would be really easy to screw things up and cause buffer overflows, memory corruption, and all sorts of other nasty problems.

But because those members are private, you can't misuse std::string. It'll always* work exactly right.

*(note that it's always possible to screw things up.... like with memcpy or with other kinds of memory corruption)

However they are quite useless otherwise and only make things more complicated.


This is the opposite of the truth.

If you write a class and it's properly encapsulated, then [after testing] you can rest easy knowing that your class "just works". Which means any code in your program that uses the class will "just work".

If you have public members everywhere and any part of your program can mess with any member of any object... what happens when bugs start popping up?

If the bug caused by the code using the class?
Or is the bug in the class itself?
How can you track them down?



Not everybody gets OOP. I didn't for a long time... until one day it just clicked.



EDIT:

As for the original question:

I suppose it depends on the situation and how complicated the class is, but I'd say just access the private members directly.

I was never a fan of pointless get/set functions that do nothing but assign and return a private variable. Such functions make even less sense when they're private.
Last edited on
closed account (1yR4jE8b)
I think the most repulsive use of a get/set function I've ever seen was:

 
member_type& getMember();


Why even bother making it private?
I agree with darkestfright.

Getters are fine if they return copies of or const references to private data members.

Getters that return non-const references and allow users to modify internal object
state directly are stupid because at that point there is no encapsulation, so you might
as well make the data members public and avoid the red tape of having to make a
function call to get at the data.


Because you can can:

1
2
3
4
#define private public
#define protected public

#include <anything> 


closed account (1yR4jE8b)
now THAT'S hideous, PanGalactic. I fear the day where I may have to work on a team with someone who would do THAT.
Yeah, preprocessor is evil.

As for private:, it is almost a comment. Proper encapsulation methods involve incomplete types, or abstract classes.
As replulsive as getMember() may be, consider two minor changes: if it did not return a reference, or if it was a const method. Then it would be another, possibly useful, level of abstraction. If the interface is kept separate from the implementation, the implementation may change without affecting end-users.

Consider:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* Truck Lib 1.0 */
class Truck
{
    int _length;
    int _width;
public:
    //...
    int getLength() { return _length; }       // does not return a reference
    const int & getWidth() const { return _width; } // const method (added const to return type per PanGalactic)
};

//...

/* end-user code: */

bool parking_space_is_big_enough_for( const Truck & truck )
{
    return( truck.getLength() < 20 && truck.getWidth() < 8 );
}

int main()
{
    if( parking_space_is_big_enough_for( truck ) )
    {
        //...
    }
    return 0;
}


Now, let's consider a case where the Truck Lib adds trailer support in version 1.1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* Truck Lib 1.1 */
class Truck
{
    int _length;
    int _width;
    int _trailer_length;
public:
    //...
    int getLength() { return _length + _trailer_length; }
    int getWidth() const { return max( _width, _trailer_length) ); } // removed the reference
};

//...

/* end-user code: */

bool parking_space_is_big_enough_for( const Truck & truck )  // method was not broken by library change
{
    return( truck.getLength() < 20 && truck.getWidth() < 8 );
}

int main()
{
    if( parking_space_is_big_enough_for( truck ) )
    {
        //...
    }
    return 0;
}


jsmith wrote:
Getters are fine if they return copies of or const references to private data members.

EDIT: I typed all of this up and submitted it before realizing that it was already said... Well, at least here's an example. :)
Last edited on
@Abramus: yes, that's why Pimpl is useful. You can't get around not having access to the implementation at all. However, Pimpl has its own cost. Though those costs are minimized with link-time optimizations. GCC should be getting that feature in 4.5.

@moorecm: your example has a couple problems. 1) v1.0 declares a const function but returns a non-const reference. 2) you changed the ABI in v1.1; every application that uses your library has to be recompiled. Returning references leads to brittle interfaces. There are very few places where it is really worth doing (a container for instance).
PanGalactic wrote:
@moorecm: your example has a couple problems. 1) v1.0 declares a const function but returns a non-const reference. 2) you changed the ABI in v1.1; every application that uses your library has to be recompiled. Returning references leads to brittle interfaces. There are very few places where it is really worth doing (a container for instance).


Thanks, I fixed the missing const above. As for the recompilation, I would consider that minor relative to requiring code changes. I was thinking about an in-house library rather than an actual 3rd party library.
Topic archived. No new replies allowed.