C++ : Private vs Public data/functions

Started by
5 comments, last by ASnogarD 13 years, 5 months ago
Hi

I just was curious about the rational for keeping data and functions in a class private for classes that wont be passed to other programmers.
I mean I am looking at some of my classes and the number of getter and setter functions just to keep the data private is ridiculous.
If I want my debug print function to output the value of a member at runtime, I need to create a whole get function ( yeah , I know it is just a return value statement but still... ).

Why not have all the data public, unless you are planning to make a library for others to use you shouldnt have to worry too much about restricting access, right ?

Do you all program strictly to the rules of data encapsulation ?

Is there some other reason for hiding data other than from users who dont know your code, or even from you accidently changing the data wrongfully ?

Its just out of curiousity born out of making one too many get functions for a simple task of checking a value :P

Thanks for reading.
Advertisement
The purpose of the getters and setters is to filter the data that you're attempting to assign a variable to.
Quote:Is there some other reason for hiding data other than from users who dont know your code, or even from you accidently changing the data wrongfully ?

Yes, the interface of your class can stay the same while the implementation changes.

The purpose of object oriented programming isn't to write more code creating trivial get/set functions for class values. The point is that the interface of the class can stay the same. You can change the structures and data used internally more freely. It's about breaking a huge problem into bite-size pieces.

Quote:Do you all program strictly to the rules of data encapsulation ?
I try to. Especially if dynamic memory management is involved.

Quote:Why not have all the data public

You can. There are cases where you want a simple trivial and transparent data structure, such as a simple 2D point. Use a "struct" in these cases.
Would you then say that ( as a very general rule ) if you need a lot of setter and getter functions, your class isnt very efficient ?

Some of my classes have equal number of set / get functions to the number of private data members... and its not like my set functions do any checks to ensure the data being set is valid.
Quote:Original post by ASnogarD

Is there some other reason for hiding data other than from users who dont know your code, or even from you accidently changing the data wrongfully ?


Yes, there is something called an invariant.

struct String {  int length;  char * data;}

Here are two variables. Each one can be changed on its own, yet their values must always remain properly linked. length indicates how many chars are in data and data must be properly allocated to hold at least that many characters.

Whenever any of these two values is changed, the other must be adjusted to preserve the invariant.

The goal of private state is to enforce such behavior.
struct String {  void resize(int newSize) {    char * newData = new char[newSize];    delete[] data;    length = newSize;    data = newData;  }  int getLength() {    return length;  }private:  int length;  char * data;}

Now there is precisely one way to modify length and the class invariant is guaranteed to be preserved. Same goes for functions - the above could call resize_internal() which, by itself, could violate one or more invariants, but would do so in private scope.

Quote:I mean I am looking at some of my classes and the number of getter and setter functions just to keep the data private is ridiculous.

This is a consequence of standardization. Variables may or may not be exposed directly. Since some variables *must* be kept private, the consistency dictates that all variables must be kept private and exposed via getters.

It is not needed, but in most cases this is how it will be done. It also depends on language used and individual project details.
Getters and setters are not encapsulation. They are marginally better than raw public variables in certain cases (e.g. you can compute results on the fly, or have simple validation checking).

90% of the time, you get a better class simply by moving away from the "access variables" way of thinking and giving the objects behaviour. For example, instead of:
player.setHealth(player.getHealth() - monster.getAttack());

You might use:
player.damage(monster.getAttack());

Which could be simplified further to:
monster.attack(player);// sample implementationvoid Monster::attack(Player &player){    player.damage(attack);}

Note that the code readability is improved, as we are know talking in the domain of game objects, and that the need for getters and setters has disappeared. This kind of "moving the logic inside the objects" is usually possible.

On the flip side, "getters" often do make sense. AI code might want to inspect how dangerous an opponent is (as a function of its attack/weapon or health values) before deciding what course of action is reasonable. UI code might need to display the players health.

However, a combination of getters and setters is indicative of pure data (for example mutable records of some description) or poorly designed objects. In the former, a all-public type might make sense (e.g. mathematical vectors). For more complex data with invariants, it might be best to keep using setters and getters despite their verbosity.

I find that 90% of classes require neither getters nor setters, ~8% might need getters and the other few percent are all-public or require both. This is just an wild approximation of course, but it illustrates the point.
Quote:Original post by ASnogarD
I just was curious about the rational for keeping data and functions in a class private for classes that wont be passed to other programmers.

One reason would be to enforce guarantees about your data by ensuring nobody (including yourself when you forget the details about what you want to enforce later on) breaks them. For example: std::vector guarantees it'll have at least vector.size() items allocated and initialized. It can't guarantee this if they instead made size a public variable.

Quote:I mean I am looking at some of my classes and the number of getter and setter functions just to keep the data private is ridiculous.

OTOH, getters and setters alone don't necessarily gain you much, if anything. Sometimes, data is just data. "All variables must be private" is extremist nonsense.

Quote:If I want my debug print function to output the value of a member at runtime, I need to create a whole get function ( yeah , I know it is just a return value statement but still... ).

The usual solution here is to just use your debugger. This isn't to say print functions are never useful but...

Quote:Why not have all the data public, unless you are planning to make a library for others to use you shouldnt have to worry too much about restricting access, right ?

Similarly, "all data public" is on the extreme side of things. If you see a way to protect yourself from future mistakes by making things private, then by all means do it - because we all make many, many mistakes.

Quote:Do you all program strictly to the rules of data encapsulation ?

Note well that getters and setters alone don't really encapsulate much if anything, especially if you're just writing them for all your private variables. You're still allowing full read and write access via your methods, and have hidden nothing about the type or anything. If all you've 'encapsulated' is the existence of a variable by exposing a new method or two, you've not done much!

Consider what kinds of methods std::vector has: push_back, insert, erase. All kinds of methods that are focused on the object as a whole, rather than it's individual members. These are the kind of things where we can start to think, "let's make this private, so this never fucks up, so thinking about the whole thing becomes simpler"
Thanks for the replies, been given a bit of food for thought...

For example my stick class , which represents a stick of dynamite being thrown in via a bad guy who is represented by a location indicator icon, has a lot of indicators to show the state of the stick ( is its flying onto the field? Is it counting down its fuse timer ? Has it been kicked out of the field ? Did it blow up ?).
Currently it uses a lot of set / get functions to change various states but I will explore the viability of creating functions that set the indicators depending on the state instead of accessing the indicators directly.

This topic is closed to new replies.

Advertisement