tags:

views:

287

answers:

8

I know the differences between public member variables and accessors on private member variables, and saw a few posts already on stack overflow about this. My question has more to do with practices though. Other than not breaking class invariants, what would usually be criterias in terms of practicality to make the member variables to be public rather than private with accessors, and vice versa? Thanks in advance for the advices.

+8  A: 

My rule of thumb is: If it's not a really simple structure (e.g. Point and Complex) implement it as accessors to private member variables. And if you are not sure if your structure is simple enough, it probably isn't ;) ..

This way, you always have the option to extend the logic of setting/getting the variable without breaking existing code. Yes, it might be a little more work to implement the accessors in the first place, but it's much much much more work to modify the code to accessors if it was a direct variable access before.

beef2k
+2  A: 

Always. Never make a member variable public. There is no advantage to it: you can always make your get and set methods inline.

Charlie Martin
Gonna have to disagree. I think there are a handful of exceptions -- a 3d Point class, for example. "Always" and "never" are dangerous words.That said, 99.9% of the time, member variables should be non-public.
rlbond
I'd rather say a strong Always and have the smallprint available on demand only to .1% that needs it ;)
Remus Rusanu
Actually, Point classes are one of the examples I use to say why it should *always* be done with accessors. Consider, with inline it's zero cost and now you're protected against a change to polar coordinates, and you have a place to go if someone wants to use a 1st quadrant co-ordinate system in place of 4th quadrant.
Charlie Martin
Well, how about std::pair? Do you think that should have accessors?
anon
Actually, yes, I think std::pair should have accessors. I keep having to remind myself that it's not foo.first(). It seems inconsistent that we have foo.first and bar.begin().
David Thornley
std::pair can't implement the Empty Base Optimization trick from boost::compressed_pair exactly because .first is too public, so that's an another argument.
MSalters
@Neil, I was busy yesterday, but yes, I'd specifically say std::pair and Point and pretty much anything else that would tempt you to make member variables visible should use accessors. I'm fond of Ruby's approach: it's not even *possible* to make members visible. Given that get/set methods in C++ impose effectively no performance cost in modern compilers, what possible reason is there to make members visible?
Charlie Martin
+1  A: 

This is a matter of encapsulation. You generally do not want to expose member variables to the caller as then you lose significant control over the state of the object. Classes with strong, simple interfaces and no exposed fields are easier to maintain, debug, and scale.

Andrew Hare
+3  A: 

The only time to use public member variables is when the class is just a "bag of bits". This means there is absolutely no chance that you will ever have to add an invariant. In that case, you should probably use a struct.

Zifre
+4  A: 

Using an accessor will enforce the client to treat the members as functions, not as raw memory. For instance it will not allow taking the address of said member. So even if the member is as POD as a simple int I still use a get-set pair of function for it. This pays of in the long run as refactoring can change the implementation w/o surprises like 'oh wait, I was taking a void* to your member'.

Performance wise all compiler will inline this set/get accessors and the assembly will look just as if referencing a public member field.

I don't think in the past 5 years I ever wrote a class that exposed its members public.

Remus Rusanu
Thanks for your advices. I have already some structures that are exposed as public, and some of them are pointers to large chunks of allocated memory. I guess it may take some work for me to get the accessors in the project. I originally didn't put them in b/c I was in the misconception that they could cause my code to run slower and more overhead.
stanigator
In what cases would a developer want to expose a member variable to public in general cases?
stanigator
If you expose 'pointers to large chunks' things may be quite a bit more complex. W/o knowing more details, the usual solution is *not* to expose an accessor to retrieve the pointer but rather expose a service (eg. a function to 'copy-out' data) or a maybe a callback (eg. a 'visitor' on the data retained internally)
Remus Rusanu
Point being that once client code knows about ur memory layout, they'll use it and you're stuck to it. Changing anything will break the code up the food chain and slowly turn into a maintenance nightmare. Hm, not even 'slowly', come to think of it...
Remus Rusanu
If there are accessors that would retrieve the pointer, would I be at the same situation where the program could turn into a nightmare to debug?
stanigator
For instance your class my later decide to support a larger buffer and it needs to keep it fragmented in memory as it cannot rely on a contiguous buffer the size it needs. An accessor to the pointer would break. A service function 'copy data out' would not.
Remus Rusanu
Accessors generally don't retrieve the pointer, but rather allow you to get and set the variable. You'd use a pointer to the object rather than a pointer to some of the internals. That works pretty well.
David Thornley
@stanigator you mention debugging. Actually accessors help debugging. At development time on debug bits at least you get to use a breakpoint on the accessor as opposed to a 'break on access' on member. On the release optimized bits the compiler will mangle your code anyway beyond any recognition and an inlined accessor will look just as baffling as a member read/write.
Remus Rusanu
+1  A: 

I think there are two important questions to ask about your data to make that decision: 1) is the data bounded by certain ranges of values? and 2) does the class depend on the consistency of the state of the data from one operation to another? If you answer "yes" to either of those questions than you had better use accessors and mutators.

For example, let's say you have a class representing a point in 2D space. If you can set that point to any arbitrary location then there is no reason to make that data private. But now lets say that the points have to be on a graph from [-100,-100] to [100,100]. In that case you would want to limit the values that the point can be assigned to (case 1).

Another example (this one is a little contrived): you have a class that represents a priority queue and you are storing the minimum value in a variable. If you change the value of that variable then it may no longer be the minimum value in which case you need to re-order the heap. Since the state of the heap depends on the value of that variable, you need to limit its access (either but not allowing it to be modified, or when it is modified re-ordering the heap as necessary).

Niki Yoshiuchi
+1  A: 

Make your data private in your class whenever it would be possible for an object of your class to be screwed up if a client changed that data, or you don't want clients dependent on your implementation of the class.

Which translates to "almost always."

JohnMcG
A: 

While most answers focus on the design / encapsulation standpoint (and I agree to the general consensus, "why not use setter / getter?"). I'd like to add that once you've hunted for a bug in some large legacy code bases, with public members, you'll never, ever, EVER, write a class without setter / getters.

Imagine the following: you have a large codebase (talking over 1M+ lines of code), where a lot of highly optimized legacy code passes pointers around, does bit twiddling etc. etc.

Now, after hours of debugging, you found that a certain member is in an inconsistent state, you're wondering "hmm, this causes the bug, now how did this member get that value..."

1) setter/getters: you put a breakpoint, 5 minutes later, bug is solved

2) public member: you're in for hours and hours of annoying detective work

Public members: don't do it, no gain, only potential pain

Pieter