I was wondering if the use of accessors can significantly affect performance of an application. Let's say we have a class Point and there are two private fields. We can get access to these fields by calling public functions such as GetX().
class Point
{
public:
Point(void);
double GetX();
double GetY();
void SetX(double x);
void SetY(double y);
~Point(void);
private:
double x,y;
};
However if we need to get the value of field x a lot of time (e.g if we process images) wouldn't this construction affect the performance of application? Maybe it would be faster just to make fields x and y public?
First and foremost, this is probably premature optimization, and in the general case accessors are not the source of application-level bottlenecks. However, they're not magic pixie dust. It's generally not the case that accessors will hurt performance. There are a few things to consider:
If the implementation is inline or if you have a toolchain that supports link-time optimization, it's likely that there will be 0 impact. Here's an example that lets you get absolutely the same performance on a compiler that doesn't suck.
class Point {
public: double GetX() const;
private: double x;
};
inline double Point::GetX() const { return x; }
If the implementation is out-of-line, then you have the added cost of a function call. If, as you say, the function is being called many times, then at least the code is more or less guaranteed to be in the cache, but the relative % of overhead may be high: the work to perform the function call is higher than the work of moving a double around, and there's a pointer indirection because the function actually uses this as a parameter.
If the implementation is both out-of-line and part of a relocatable library (Linux *.so or Windows *.dll), there's an additional indirection that occurs in order to manage the relocation.
Both of the latter costs are reduced on x86-64 hardware relative to x86 32-bit; so much so that you should just not worry about it. I can't speak about other architectures.
Penultimately, if you have many trivial objects with trivial getters and setters, and if you have no profile-guided optimization or link-time optimization, there may be caching effects due to large numbers of tiny functions. It's likely that each function requires a minimum of one cache line, and the functions are not going to be naturally organized in a way that groups commonly-used sections together. This cost is something you should probably ignore unless you're writing a very large-scale C++ project or core component, such as the KDE base system.
Ultimately, don't worry about it.
Such methods should always be inlined by the compiler and the performance of that will be identical to making them public. You can use the inline keyword to help the compiler along, but that's just a hint. If it's really critical that you avoid function call overhead, read the generated assembly. If they're getting inlined you're ok. Otherwise you might want to consider loosening their visibility.
In a typical case, no, there will not be a difference in performance (unless you've fairly specifically told the compiler not to inline any functions). If you allow it to inline functions, however, chances are that it'll generate identical assembly language for both.
That should not, however, be seen as an excuse for ruining your design by including these abominations. First of all, a class should generally provide high level operations, so (for example) you could have a move_relative and move_absolute, so instead of something like this:
Point whatever;
whatever.SetX(GetX()+3);
whatever.SetY(GetY()+4);
...you'd do something like this:
Point whatever;
whatever.move_relative(3, 4);
There are times, however, that exposing something as data really does make sense and work well. If/when you are going to do that, C++ already provides a good way to encapsulate access to the data: a class. It also provides a predefined name for SetXXX and GetXXX -- they're operator= and operator T respectively. The right way to do this is something like this:
template <class T>
class encapsulate {
T value;
public:
encapsulate(T const &t) : value(t) {}
encapsulate &operator=(encapsulate const &t) { value = t.value; }
operator T() { return value; }
};
Using this, your Point class looks like:
struct Point {
encapsulate<double> x, y;
};
With this, the data you want to be public looks and acts as if it is. At the same time, you retain full control over getting/setting the values by changing the encapsulate to something that does whatever you need done.
Point whatever;
whatever.x = whatever.x + 3;
whatever.y = whatever.y + 4;
Though I haven't bothered to in the demo template above, it's fairly easy to support the normal compound assignment operators (+=, -=, *=, /=, etc.) as well. Depending on the situation, it's often useful to eliminate many of these though. Just for example, adding/subtracting to an X/Y coordinate often makes sense -- but multiplication and division frequently won't, so you can just add += and -=, and if somebody accidentally types in /= or |= (for just a couple of examples), their code simply won't compile.
This also provides better enforcement of whatever constraints you need on the data. With private data and an accessor/mutator, other code in the class can (and almost inevitably will) modify the data in ways you didn't want. With a class dedicated to nothing by enforcing the correct constraints, that issue is virtually eliminated. Instead, code both inside and outside the class does a simple assignment (or uses the value, as the case may be) and it's routed through the operator=/operator T automatically -- code inside the class can't bypass whatever checking is needed.
Since you're (apparently) concerned with efficiency, I'll add that this won't normally have any run-time cost either. In fact, being a template gives it a slight advantage in that regard. Where code in a normal function could (even if only by accident) be rewritten in a way that prevented inline expansion, using a template eliminates that -- if you try to rewrite it in a way that otherwise wouldn't generate inline code, with a template it won't compile at all.
As long as you define the functions in the header so the compiler can inline them there should be no difference at all. But even if they aren't inlined you still shouldn't make them public unless profiling indicates that it's a significant bottleneck and that making the variables public improves the problem. Making variables public decreases encapsulation and maintainability. For a bit more on public variables, see my answer on What good are public variables then?
The short answer is yes, this will affect the performance. Whether you will notice the difference or not is another matter that depends on how much code you have in the accessors, among other things.
The more important questions, though, is do you need what you gain from using accessors? If you make the fields public, then you lose control over their values. Do you want to allow x or y to be NaN? or +-infinity? Making them public would make such cases possible.
If you decide later that a double is not acceptable for your point class (maybe you need more precision or the precision isn't necessary), then accessing the fields directly would cause trouble. While this change might also require changes in the accessors, the setters should be fine with overloaded methods. And you may still be fine with a public representation of a double whereas the internal representation is not a double (although this is not so likely with a Point class, I imagine).
There are other cases where you might want to have side effects on accessors and setters as well that making the fields public would circumvent. Maybe you want to create events for when your point changes, but if the fields are public, then your class won't know when the values change.
ADDED
Ok, so my glossing over with my "yes" so that I could get to the non-performance issues that I felt more important wasn't appreciated.
In many cases, the yes is probably as correct as it will be imperceptible. True, using inline and a kick-ass compiler may very well end up with the same code (assuming an accessor like double GetX() { return x; }), but there are a lot of ifs there. Compilers will only inline things that end up in the same object file (often created from a single code file). So you also need a kick-ass linker to optimize the references in other object files (by the time you get to the linker, the inline hint may not even still remain in the code). So some, but not necessarily all, of the code may end up being identical, but that would be something you can confirm only after the fact and isn't useful.
If you're concerned about image processing then it might be worth allowing for friend classes so that an image class that you code can have access directly to the fields, but again I don't think that even in that case the accessor will be adding a lot to your runtime.
Related
I've been working for longer now with the 3ds max SDK, which in nearly all parts doesn't use const at all. So even a Width() or Height() getter of a Bitmap isn't marked as const. This has been already a real annoyance in small projects, but since I've been working on a larger project, it becomes increasingly terrible.
For example, I am holding a single Bitmap instance as a shared_ptr<Bitmap> member in multiple class instances out of performance reasons. Of course there are cases I want to avoid by all means that a single instance may change the properties for all instances, thus all raw pointer getters (necessary for the SDK) deliver a const Bitmap*. Unfortunately, now I can't even ask the const Bitmap* for its width - because Width() is non-const.
I'm asking myself what is the best way to deal with this. I see three options:
Forget about const completely, make everything non-const. In the smaller projects I used to do this, but like I said, with more sophisticated techniques, it becomes more dangerous.
Make an inplace const_cast at every place it's necessary. That will be at many places, and it's pretty bad to read.
Write wrappers for the 3ds max classes, which provide const methods at least for the methods which are highly presumably safe. This would encapsulate all the const_cast in one place and be also suitable for other projects.
I have been warned (and I know) that this might be opinion-based. But I had to deal with this annoying problem for a long time now, and I'd really like to find a solution and thus need the experience of others.
First of all, I would like to mention that lack of const correctness may be justifiable by implementation details, for example getter function may perform lock on internal synchronization primitive and therefore always alters internal state and can not be marked as const:
int Bitmap::Width(void)
{
int width{};
::std::lock_guard<::std::mutex> const lock{m_sync};
width = m_width;
return width;
}
As a workaround you can write a dedicated PImpl bitmap wrapper restricting direct access to bitmap implementation forwarding functions of interest with appropriate const qualifiers:
class SharedBitmap
{
private: ::std::shared_ptr<Bitmap> m_p_bitmap;
public: int Width(void) const
{
return m_p_bitmap->Width();
}
// other methods...
};
Note that this approach is different from third option listed in question as it does not involve const_cast.
In my experience (10yr), "const" has been a greater nusiance than it has been helpful. Not to mentions code getting longer, ergo harder to read. If you want to know how a library works, you read the manual anyway, not the header. If you want to know you did it right, you run functional tests. Hell there are even static analysis tools checking if a variable is ever written to, without burdening the code with useless non-functional metadata to capture undocumented usage patterns. And since there are a many ways to break const, it is the right way of capturing such errors.
In summary, option 1 is in my experience the most efficient solution. (Is this an opinion? Those who disagree will probably think so.)
For that quick post-purge of const you could do #define const or even -Dconst to remove it, though whether it is safe may depend on your specific scenario, one illegal use is doing this for the standard headers. I have done similar hacks like #define private|protected public instead of messing with friend when doing white box testing, works like a charm!
Know that the concept of "constant variable" is void in many programming languages and they seem to do just fine without it.
The only time you need const is in the case of C-string constants / string literals. Does not seem to be your case though.
Is it a conceivable that a C++ compiler would optimize out a function call to a class member function that only sets class variables? Example:
class A
{
private:
int foo;
public:
void bar(int foo_in)
{
foo = foo_in;
}
}
So if I did this
A test;
A.bar(5);
could a compiler optimize this to directly access the member and set it like so?
Yes, it is called inlining.
Moreover c++ is designed specifically to support, or make it easier for the compiler to perform, such optimizations in quite complex inheritance cases and templates.
Some would say this is quite distinctive feat of c++ as a high level language compared to others. Its "high level" features (mostly I mean generic programming - templates) were designed with such optimizations in mind. It is also one of the reasons that makes it considered as efficient in terms of performance.
This is also why would I expect a decent job at working out inlines with any reputable compiler.
From what I've read, this is also the reason why it is hard to get all the fancy stuff of other high-level languages such as Reflection mechanism, or other known from e.g. Java or python. It is because c++ is designed to easily allow to inline pretty much everything possible, so it's hard to introspect optimized code.
Edit:
Because you said you are writing an OpenGL stuff where performance of setters and getter and such optimizations do matter I decided to elaborate a bit and show a bit more interesting example where you can rely on inline mechanism.
You can write some interfaces avoiding the virtual mechanism but using templates. E.g:
//This is a stripped down interface for matrices for physical objects
//that have Hamiltonian and you can apply external field and temperature to it
template< class Object >
class Iface {
protected:
Object& t;
public:
Iface(Object& obj) : t(obj) {};
Vector get_eigen_vals() {return t.get_eigen_vals(); };
Matrix get_eigen_vectors() {return t.get_eigen_vectors(); };
void set_H(VectorD vect) { t.set_H(vect); };
void set_temp(double temp) {t.set_temp(temp);};
};
If you declare interface like this, you can wrap an object with this interface object, and pass instance of this interface class to your functions/algorithms, and still have everything inlined because it works on the reference of Object. Good compiler optimizes whole Iface out.
To answer the question a little bit more generally than just inlining:
There is something in the standard known as the as-if rule. It says that the compiler is allowed to make any change to your program as long as it doesn't affect the observable behaviour. There are even exemptions that allow them to change things that technically do change the observable behaviour.
It can elide function calls and even complete classes. It can do basically whatever it wants as long as it doesn't break anything.
Yes, the compiler can optimize this call away.
This is, actually very simple case of inlining.
The compiler is allowed to do much more tan that (it can unfold loops, optimize out local variables replace calculations with constants etc.)
Okay, just about everywhere I read, I read that getters/setters are "evil".
Now, as a programmer who uses getters/setters often in PHP / C#, I do not see how they are alive. I have read that they break encapsulation, etc etc, however, here is a simple example.
class Armor{
int armorValue;
public:
Armor();
Armor(int); //int here represents armor value
int GetArmorValue();
void SetArmorValue(int);
};
Now, lets say getters and setters are "evil".
How are you supposed to change a member variable after initialization.
Example:
Armor arm=Armor(128); //armor with 128 armor value
//for some reason I would like to change this armor value
arm.SetArmorValue(55); //if i do not use getters / setters how is this possible?
Lets say the above is not okay, for whatever reason.
What if my game restricts armor values from 1 to 500. (No armor can have a piece that has more than 500 armor or less than 1 armor).
Now my implementation becomes
void Armor::SetArmor(int tArmValue){
if (tArmValue>=1 && tArmValue<=500)
armorValue=tArmValue;
else
armorValue=1;
}
So, how else would I impose this restriction without using getters/setters?
How else would I modify a property without using getters/setters?
Should armorValue just be a public member variable in case 1, and the getters/setters used in case 2?
Curious. THanks guys
You have misunderstood something. Not using getters/setters breaks encapsulation and exposes implementation details, and can be considered "evil" for some definition of evil.
I guess they can be considered evil in the sense, that without proper IDE/editor support, they are somewhat tediois to write in C++...
One pitfall of C++ is to create non-const reference getter, which allows also modification. That's same as returning a pointer to internal data, and will lock that part of internal implementation, and is really no better than making field public.
Edit: based on comments and other answers, what you heard probably refers to always creating non-private getter and setter for every field. But I would not call that evil either, just stupid ;-)
Being slightly contrarian: yes, getters and setters (aka accessors and mutators) are mostly evil.
The evil here is not, IMO, so much from "breaking encapsulation", as from simply defining a variable to be of one type (e.g., int) when it's really not that type at all. Looking at your example, you're calling Armor an int, but it's really not. While it's undoubtedly an integer, it's certainly not an int, which (among other things) defines a range. While your type is an integer, it's never intended to support the same range as an int at all. If you want Armor to be of a type integer from 1 to 500, define a type to represent that directly, and define Armor as an instance of that type. In this case, since the invariant you want to enforce is defined as part of the type itself, you don't need to tack a setter onto it to try to enforce it.
template <class T, class less=std::less<T> >
class bounded {
const T lower_, upper_;
T val_;
bool check(T const &value) {
return less()(value, lower_) || less()(upper_, value);
}
void assign(T const &value) {
if (check(value))
throw std::domain_error("Out of Range");
val_ = value;
}
public:
bounded(T const &lower, T const &upper)
: lower_(lower), upper_(upper) {}
bounded(bounded const &init)
: lower_(init.lower), upper_(init.upper), val_(init.val_)
{ }
bounded &operator=(T const &v) { assign(v); return *this; }
operator T() const { return val_; }
friend std::istream &operator>>(std::istream &is, bounded &b) {
T temp;
is >> temp;
if (b.check(temp))
is.setstate(std::ios::failbit);
else
b.val_ = temp;
return is;
}
};
With this in place, defining some armor with a range of 1..500 becomes utterly trivial:
bounded<int> armor(1, 500);
Depending on the situation, you might prefer to define (for example) a saturating type where attempting to assign an out of range value is fine, but the value that actually is assigned will simply be the nearest value that is within range.
saturating<int> armor(1, 500);
armor = 1000;
std::cout << armor; // prints "500"
Of course, what I've given above is also a bit bare-bones. For your armor type, it would probably be convenient to support -= (and possibly +=) so an attack would end up something like x.armor -= 10;.
Bottom line: the (or at least "one") major problem with getters and setters is that they usually point to your having defined a variable as being of one type when you really want some other type that happened to be sort of similar in a few ways.
Now, it's true that some languages (e.g., Java) fail to provide the programmer with the tools necessary to write code like that. Here I'm trusting your use of the C++ tag to indicate that you really do want to write C++ though. C++ does provide you with the necessary tools, and (at least IMO) your code will be better off for your making good use of the tools it provides so your type enforces the required semantic constraints while still using clean, natural, readable syntax.
In short: they aren't evil.
It's nothing wrong with them as long as they don't leak out the internal representation. I see no problems here.
A common criticism of get/set functions is that they can be abused by client code to perform operations that logically should be encapsulated in the class. For example, say a client wants to "polish" their armour, and decides the effect is to increase "value" by 20, so they do their little get and set thing and are happy. Then someone other client code elsewhere decides rusty armour should drop the value by 30, and they do their bit. Meanwhile, a dozen other places in client code are also allowing polishing and rusting effects on armour - as well as say "reinforcing" and "cracking", and implementing them directly. There's no central control of this... the maintainer of the armour class has no ability to do things like:
have the rust, polish, reinforce and crack effects apply at most once per piece of armour
tune the number added to or subtract from value for specific logical effects
decide that the new "leather" armour type can't rust, and ignore client attempts to make it do so
On the other hand, if the first client that wanted to make armour rusty couldn't do so through the interface, they'd go to the maintainer of the armour class and say "hey, give me a function to do this", then other people could start using the logical-level "rust" operation, and if it became useful later to do the kinds of things I describe above they could be implemented easily and centrally in the armour class (e.g. by having a separate boolean to say if the armour was rusty, or a separate variable recording the rust effect).
So, the thing with get/set functions is they frustrate the natural evolution of an API of logical functionality, instead distributing logic throughout client code, leading in extremis to an unmaintainable mess.
Your getter/setter looks ok.
The alternative to getter/setters is to make member variables public. To be more precise, group variables into structure without member functions. And operate on this structure within your class
Giving access to members reduces encapsulation, but sometimes it's necessary. And the best way to do it is by means of getters and setters. Some people implement them when no such access is necessary, just because they can and it's a habit.
Getters are evil whenever:
They access directly data members of the class
When you have to add new getter every time you add data to the class
The data behaviour is different in each getter
Good getters would thus do the following:
They forward the request to some other object or collect the data from several places
You can fetch large amounts of data using just one getter
All the data you fetch is handled the same way
Setters on the other hand are evil always.
how else would I impose this restriction without using getters/setters? How else would I modify a property without using getters/setters?
You can check what you read from the variable and if its value is out of range use a predefined value instead (if possible).
You can also resort to dirty hacks such as protecting the memory underneath the variable from writing, catching write attempts and disallowing/ignoring the ones with invalid values. This is going to be cumbersome to implement and expensive to execute. It may be useful for debugging, though.
I'm making a very simple class to represent positions in 3D space.
Currently, I'm just letting the user access and modify the individual X, Y and Z values directly. In other words, they're public member variables.
template <typename NumericType = double>
struct Position
{
NumericType X, Y, Z;
// Constructors, operators and stuff...
};
The reasoning behind this is that, because NumericType is a template parameter, I can't rely on there being a decent way to check values for sanity. (How do I know the user won't want a position to be represented with negative values?) Therefore, there's no point in adding getters or setters to complicate the interface, and direct access should be favored for its brevity.
Pos.X = Pos.Y + Pos.Z; // Versus...
Pos.SetX(Pos.GetY() + Pos.GetZ());
Is this an okay exception to good practice? Will a (hypothetical) future maintainer of my code hunt me down and punch me in the face?
The idea behind using getters and setters is to be able to perform other behavior than just setting a value. This practice is recommended because there are a multitude of things you might want to retrofit into your class.
Common reasons to use a setter (there are probably more):
Validation: not all values allowed by the type of the variable are valid for the member: validation is required before assignment.
Invariants: dependent fields might need to be adjusted (e.g. re-sizing an array might require re-allocation, not just storing the new size).
Hooks: there is extra work to perform before/after assignment, such as triggering notifications (e.g. observers/listeners are registered on the value).
Representation: the field is not stored in the format "published" as getters and setters. The field might not even stored in the object itself; the value might be forwarded to some other internal member or stored in separate components.
If you think your code will never, ever use or require any of the above, then writing getters and setters by principle is definitely not good practice. It just results in code bloat.
Edit: contrarily to popular belief, using getters and setters is unlikely to help you in changing the internal representation of the class unless these changes are minor. The presence of setters for individual members, in particular, makes this change very difficult.
Getters and setters are really only an important design choice if they get/set an abstract value that you may have implemented in any number of ways. But if your class is so straight-forward and the data members so fundamental that you need to expose them directly, then just make them public! You get a nice, cheap aggregate type without any frills and it's completely self-documenting.
If you really do want to make a data member private but still give full access to it, just make a single accessor function overloaded once as T & access() and once as const T & access() const.
Edit: In a recent project I simply used tuples for coordinates, with global accessor functions. Perhaps this could be useful:
template <typename T>
inline T cX(const std::tuple<T,T,T> & t) { return std::get<0>(t); }
typedef std::tuple<double, double, double> coords;
//template <typename T> using coords = std::tuple<T,T,T>; // if I had GCC 4.8
coords c{1.2, -3.4, 5.6};
// Now we can access cX(c), cY(c), cZ(c).
Took me a while, but I tracked this old Stroustrup interview down, where he discusses exposed-data structs versus encapsulated classes himself: http://www.artima.com/intv/goldilocks3.html
Getting more heavily into specifics, there's are dimensions to this that may be missing / understated in existing answers. The benefits of encapsulation increase with:
re-compilation/link dependency: low-level library code that is used by large numbers of applications, where those apps may be time-consuming and/or difficult to recompile and redeploy
it's usually easier if implementation was out-of-line (which may require pImpl idiom and performance compromises) so you only have to relink, and easier still if you can deploy new shared libraries and simply bounce the app
by way of contrast, there's massively less benefit from encapsulation if the object's only used in "non-extern" implementation of a specific translation unit
interface stability despite implementation volatility: code where the implementation is more experimental / volatile, but the API requirement is well understood
note that by being careful it may be possible to give direct access to member variables while using typedefs for their types, such that a proxy object can be substituted and support identical client-code usage while invoking different implementation
If you do some very easy stuff your solution could be just fine.
If you later realize that calculations in a spherical coordinate system are much easier or faster (and you need performance), you can count on that punch.
It is ok for such well known structure that :
Can have any possible values, like an int;
Should operate like a built-in type when manipulating it's value, for performance reasons.
However, if you need more than a type that "just is a 3D vector", then you should wrap it in another class, as private member, that would then expose x, y and z through member functions and additional features member functions.
The reasoning behind this is that, because NumericType is a template parameter, I can't rely on there being a decent way to check values for sanity. (How do I know the user won't want a position to be represented with negative values?)
The language and compilers support this case well (via specialization).
Therefore, there's no point in adding getters or setters to complicate the interface, and direct access should be favored for its brevity.
Moot argument -- see above.
Is this an okay exception to good practice?
I don't think it is. Your question implies validation should exist, but it's not worth implementing/supporting because you've chosen to use a template in your implementation, and not specialize appropriate for the language feature you've chosen. By that approach, the interface only appears to be partially supported -- those missing implementations will just pollute clients' implementations.
I personally find it weird/ugly when a class uses a getter to access its own member data. I know the performance impact is none but I just don't like to see all those method calls.
Are there any strong arguments either way, or is it just one of those things that's personal preference and should be left to each coder, or arbitrarily controlled in a coding standard?
Update: I'm meaning simple getters, specifically for a class' non-public members.
The reason you might want to use a getter/setter is because it conceals the implementation. You won't have to rewrite all of your code if you are using getters/setters in case the implementation does change, because those members can continue to work.
EDIT based on the many clever comments:
As for a class using setters and getters on itself, that may depend on the particulars. After all, the implementation of a particular class is available to the class itself. In the cases where a class is normally instantiated, the class should use the member values directly for its own members (private or otherwise) and its parent classes (if they are protected) and only use getters/setters in the case that those members are private to the parent class.
In the case of an abstract type, which will usually not contain any implementation at all, it should provide pure virtual getters and setters and use only those in the methods it does implement.
Willingness to use getters/setters within class member implementation is the canary in the mine telling that your class is growing unreasonably. It tells that your class is trying to do too many different things, that it serves several purposes where it should serve one instead.
In fact, this is usually encountered when you are using one part of your class to store or access your data, and another part to make operations on it. Maybe you should consider using a standalone class to store and give access to your data, and another one to provide a higher view, with more complex operations with your data.
THE OBVIOUS
getters and setters for protected members makes as much sense as for public... derived classes are just another form of client code, and encapsulating implementation details from them can still be useful. I'm not saying always do it, just to weight pros and cons along the normal lines.
getters and setters for private members is rarely a net benefit, though:
it does provide the same kind of encapsulation benefits
single place for breakpoints/logging of get/set + invariant checks during dev (if used consistently)
virtual potential
etc...
but only to the presumably relatively small implementation of the same struct/class. In enterprise environments, and for public/protected member data, those benefits can be substantial enough to justify get/set methods: a logging function may end up having millions of lines of code depedent on it, and hundreds or thousands of libraries and apps for which a change to a header may trigger recompilation. Generally a single class implementation shouldn't be more than a few hundred (or at worst thousand) lines - not big or complex enough to justify encapsulating internal private data like this... it could be said to constitute a "code smell".
THE NOT-SO OBVIOUS
get/set methods can very occasionally be more readable than direct variable access (though more often less readable)
get/set methods may be able to provide a more uniform and convenient interface for code-generated member or friend methods (whether from macros or external tools/scripts)
less work required to transition between being a member or friend to a freestanding helper function should that become possible
implementation may be rendered more understandable (and hence maintainable) to people who're normally only users of the class (as more operations are expressed via, or in the style of, the public interface)
It's a bit out of scope for the question, but it's worth noting that classes should generally provide action-oriented commands, event-triggered callbacks etc. rather than encouraging a get/set usage pattern.
It seems most people didn't read your question properly, the question is concerning whether or not class methods accessing its own class' members should use getters and setters; not about an external entity accessing the class' members.
I wouldn't bother using getter and setter for accessing a class' own members.
However, I also keep my classes small (typically about 200-500 lines), such that if I do need to change the fields or change its implementations or how they are calculated, search and replace wouldn't be too much work (indeed, I often change variable/class/function names in the early development period, I'm picky name chooser).
I only use getter and setters for accessing my own class members when I am expecting to change the implementation in the near future (e.g. if I'm writing a suboptimal code that can be written quickly, but plans to optimize it in the future) that might involve radically changing the data structure used. Conversely, I don't use getter and setter before I already have the plan; in particular, I don't use getter and setter in expectation of changing things I'm very likely never going to change anyway.
For external interface though, I strictly adhere to the public interface; all variables are private, and I avoid friend except for operator overloads; I use protected members conservatively and they are considered a public interface. However, even for public interface, I usually still avoid having direct getters and setters methods, as they are often indicative of bad OO design (every OO programmers in any language should read: Why getter and setter methods are Evil). Instead, I have methods that does something useful, instead of just fetching the values. For example:
class Rectangle {
private:
int x, y, width, height;
public:
// avoid getX, setX, getY, setY, getWidth, setWidth, getHeight, setHeight
void move(int new_x, int new_y);
void resize(int new_width, int new_height);
int area();
}
The only advantage is that it allows changing internal representation without changing external interface, permitting lazy evaluation, or why not access counting.
In my experience, the number of times I did this is very, very low. And it seems you do, I also prefer to avoid the uglyness and weightyness of getter/setters. It is not that difficult to change it afterwards if I really need it.
As you speak about a class using its own getter/setters in its own implementation functions, then you should consider writing non-friend non-member functions where possible. They improve encapsulation as explained here.
An argument in favor of using getters is that you might decide one day to change how the member field is calculated. You may decide that you need it to be qualified with some other member, for instance. If you used a getter, all you have to do is change that one getter function. If you didn't you have to change each and every place where that field is used currently and in the future.
Just a crude example. Does this help?
struct myclass{
int buf[10];
int getAt(int i){
if(i >= 0 && i < sizeof(buf)){
return buf[i];
}
}
void g(){
int index = 0;
// some logic
// Is it worth repeating the check here (what getAt does) to ensure
// index is within limits
int val = buf[index];
}
};
int main(){}
EDIT:
I would say that it depends. In case the getters do some kind of validation, it is better to go through the validation even if it means the class members being subjected to that validation. Another case where going through a common entry point could be helpful is when the access needs to be essentially in a sequential and synchronized manner e.g. in a multithreaded scenario.
Protecting a member variable by wrapping its access with get/set functions has its advantages. One day you may wish to make your class thread-safe - and in that instance, you'll thank yourself for using those get/set functions
this is actually for supporting the object oriented-ness of the class by abstracting the way to get(getter). and just providing its easier access.
Simple answer. If you are writing a one shoot program, that will never change, you can leave the getters at peace and do without any.
However if you write a program that could change or been written over time, or others might use that code, use getters.
If you use getters it helps change the code faster later on, like putting a guard on the property to verify correctness of value, or counting access to the property(debugging).
Getters to me are about easy possibilities(free lunch). The programmer who write the code does not need getters, he wants them.
hope that help.
My thoughts are as follows.
Everything should be static, constant, and private if possible.
As you need a variable to be instanced meaning more than one unique
copy you remove static.
As you need a variable to be modifiable you remove the const.
As you need a class/variable to be accessed by other classes you remove
the private.
The Usage of Setters/Getters - General Purpose.
Getter's are okay if the value is to ONLY be changed by the class and
we want to protect it. This way we can retrieve the current state of
this value without the chance of it's value getting changed.
Getter's should not be used if you are planning to provide a Setter
with it. At this point you should simply convert the value to public
and just modify it directly. Since this is the intent with a Get/Set.
A Setter is plain useless if you are planning to do more then simply
"this.value = value". Then you shouldn't be calling it "SetValue"
rather describe what it is actually doing.
If let's say you want to make modifications to a value before you
"GET" it's value. Then DO NOT call it "GetValue". This is ambiguous
to your intent and although YOU might know what's happening. Someone
else wouldn't unless they viewed the source code of that function.
If let's say you are indeed only Getting/Setting a value, but you are
doing some form of security. I.e. Size check, Null Check, etc.. this
is an alternative scenario. However you should still clarify that in
the name E.g. "SafeSetValue" , "SafeGetValue" or like in the "printf"
there is "printf_s".
Alternatives to the Get/Set situations
An example that I personally have. Which you can see how I handle a
Get/Set scenario. Is I have a GameTime class which stores all kinds
of values and every game tick these values get changed.
https://github.com/JeremyDX/DX_B/blob/master/DX_B/GameTime.cpp
As you will see in the above my "GETS" are not actually "GETS" of
values except in small cases where modification wasn't needed. Rather
they are descriptions of values I am trying to retrieve out of this
GameTime class. Every value is "Static Private". I cannot do Const
given the information is obtained until runtime and I keep this
static as there is no purpose to have multiple instances of Timing.
As you will also see I don't have any way of performing a "SET" on any of this data, but there are two functions "Begin()" and "Tick()" which both change the values. This is how ALL "setters" should be handled. Basically the "Begin()" function resets all the data and loads in our constants which we CANT set as constants since this is data we retrieve at runtime. Then TICK() updates specific values as time passes in this case so we have fresh up to date information.
If you look far into the code you'll find the values "ResetWindowFrameTime()" and "ElapsedFrameTicks()". Typically I wouldn't do something like this and would have just set the value to public. Since as you'll see I'm retrieving the value and setting the value. This is another form of Set/Get, but it still uses naming that fits the scenario and it uses data from private variables so it didn't make sense to pull another private variable and then multiply it by this rather do the work here and pull the result. There is also NO need to edit the value other then to reset it to the current frame index and then retrieve the elapsed frames. It is used when I open a new window onto my screen so I can know how long I've been viewing this window for and proceed accordingly.