What's the point of private class members and methods(C++)

Started by
18 comments, last by davepermen 11 years, 11 months ago
One advanced and very important concept that you may come across in the foreseeable future, is the idea of the separation of a class's interface with its implementation. Such concepts are extremely powerful, allowing class implementers to change their classes at will, so long as the original interface doesn't change. Such concepts are used regularly, for example in patching up and updating software via the internet, something that virtually all of us have done at one time or another. So, regardless of your particular points of view on this topic, you too have been benefiting from these ideas!

Indeed there are languages around, such as the Interface Definition Language (IDL), whose sole purpose is to define interfaces only, allowing class implementations to remain private and totally encapsulated. Some implementations will even be beyond any means to hack, as outlined by Dave above, because with this ability of being able to separate interface from implementation, the implementation doesn't even need to be on the host machine!

Anyway, I digress. All I am saying is, don't take this concept too lightly. I too believe that, with time, your opinion will change. Encapsulating software is one of the most fundamental concepts to have emerged over the past few decades. Indeed, perhaps such a powerful concept was one of the reasons why Bjarne Stroustrup developed C++ in the first place!
Advertisement

Because it makes me have to write more code to interface between the public and private parts of the class. This, in turn, increases the time I spend on the project for no gain. I know how the class works and how to use it because I wrote it.


If you're talking about the need to make Get/Set functions for every single data member, then I'd agree that this is only marginally better encapsulated than just making that data public. It does have some advantages: at least those accessors can maintain/check your class invariants. But still, it's kind of missing the point. As a general rule, if you find yourself wanting accessors all over the place, your class is poorly thought out and would probably benefit from a rethink.

If you're talking about the need to make Get/Set functions for every single data member

This is where templates can come in play. It's not hard to overload operator= to set/get values, if you need something custom just pass lambda or make specialized template and you're all set. Compiler should inline everything, making interface look all public while it's actually all private except methods.

Can't seem find original article, but this should give general idea:

template<typename T, T DefaultValue>
struct PropertyBasic {
private:
T value;
public:
PropertyBasic() : value(DefaultValue) { }
operator T () { return value; }
T operator=(const T &newValue) { return value = newValue; }
};

template<typename T, T DefaultValue, typename Setter>
struct PropertySetter {
private:
T value;
public:
PropertySetter() {
Setter::set(value, DefaultValue);
}
operator T () { return value; }
T operator=(const T &newValue) {
return Setter::set(value, newValue);
}
};

struct MyClass {
struct mysetter {
static int set(int &value, int newValue) { return value = newValue * 2; }
};
PropertyBasic<int, 10> Health;
PropertySetter<int, 10, mysetter> VariableWhichDoublesSetValue;
};

void main() {
MyClass foo;

foo.Health = 100;
cout << foo.Health << endl; // 100

foo.VariableWhichDoublesSetValue = 99;
cout << foo.VariableWhichDoublesSetValue << endl; // 198
}


P.S. Ignore bad style and stuff.

[quote name='Sandman' timestamp='1337100228' post='4940457']
If you're talking about the need to make Get/Set functions for every single data member

This is where templates can come in play. It's not hard to overload operator= to set/get values, if you need something custom just pass lambda or make specialized template and you're all set. Compiler should inline everything, making interface look all public while it's actually all private except methods.
[/quote]

Finding cleverer ways of implementing accessors like this might be neat from a language point of view, but it's still kind of missing the point. *Not to mention the fact that overloading operators in non-standard ways can make your code incredibly difficult to follow, and is something that should be done only with great caution. If I see functions called 'SetFoo(int)' and 'SetBar(float)' I have a vague idea what they do: with an overloaded operator = I get nothing.

The key point is that a well encapsulated class is not a great big blob of data to be poked around in by anyone who cares to look, it's an implementation of some piece of functionality - and the details of how that implementation works (and the data it needs to get there) should not be exposed outside of that class, except where absolutely necessary. The main thing I'm trying to get across is that having access to all of a class's private members not only annoying to write, but it's still poor encapsulation, and in the vast, vast majority of cases, completely unnecessary.

*edit: ah ok I see your edit now, so the warning about operator overloading isn't really relevant. Still, the point about accessors being largely unnecessary holds.
When it comes to making things private I like to think of it like this; the person who is going to maintain and work with this code is an idiot who hates you aka yourself in 6 months when you've forgotten WHY you done things.

I mostly base this on my tendency to come back to code I've written on a friday on a monday morning and spend the first 20mins trying to work out just how high I was at the time of writing it :D

Can't seem find original article, but this should give general idea:


Personally I prefer to avoid the setter part and stick with
property() //getter
property(value) //setter

Ie. overload operator() for both instead of using = for the setter

The idea is that all "default" stuff can be handled with a property template and when you actually do need special get/set behaviour you go back to a private variable with appropriately named get/set function. To the outside it will look exactly the same, be a familiar style (QT and parts of the C++SL use it as well) and it won't give the illusion of directly accessing a variable (which I feel = does).
f@dzhttp://festini.device-zero.de

Personally I prefer to avoid the setter part and stick with
property() //getter
property(value) //setter


That could work as well. However, I prefer player.position = player.position + player.velocity; instead of player.position(player.position() + players.velocity());.
First way makes more sense to me, but it's just matter of perspective I guess.

Private state encapsulates class invariants.


And as we know, enforcing invariants is the only valid reason to create a class. (to paraphrase Stroustrup)

Rather than asking "what are private members for?", better to ask "what are public members for?" and "why am I creating these class things anyway?"
[size="1"]

That could work as well. However, I prefer player.position = player.position + player.velocity; instead of player.position(player.position() + players.velocity());.
First way makes more sense to me, but it's just matter of perspective I guess.


I prefer player.update(delta) personally. The specifics of what that does is up to the player, not calling code.

I know how the class works and how to use it because I wrote it.


correct this to


I NEED TO know how the class works and how to use it ALL THE TIME because I wrote it.


if you properly hide the stuff you don't need from the outside, you don't NEED TO know how the class works anymore. you can then use your mind for more important stuff: the NEXT thing you do.
If that's not the help you're after then you're going to have to explain the problem better than what you have. - joanusdmentia

My Page davepermen.net | My Music on Bandcamp and on Soundcloud

This topic is closed to new replies.

Advertisement