If class is just behaviorless aggregate of data, it is fine to make it a class with all members public (often keyword
struct
is used to denote that). Otherwise you want private data: even if there is nothing which seems to suggest using accessors, it might change. For example:
There was a class called
Bad representing entity which has a property
foo and property
bar, which can be calculated from foo using complex formula. It looked like this:
1 2 3 4 5 6
|
class Bad
{
public:
int foo;
int bar() const { return do_complex_calculations(foo); }
}
|
Later it was found that users are requesting bar way more than accessing foo. More to that, users tends to have accesses to foo and bar to be separate from each other with calls to same property clumped together. Solution is simple: cache result of calling bar and recalculate it if it is dirty: wasn't calculated before or depended upon value changed. It would be simple if we could do additional actions when
foo is accessed. Which we cannot, as it is public and modifiable directly by anyone. It was solved, but at what cost:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
class Bad
{
public:
int foo;
int bar() const
{
if(foo == foo_prev) {
return bar_cache;
} else {
foo_prev = foo;
return bar_cache = do_complex_calculations(foo);
}
}
private:
int foo_prev;
int bar_cache;
}
|
Additional member (increasing size) and complex logic (reducing perfomance gain).
Now imagine if there several such members of complex types, increasing size and reducing perfomance drastically? It wouldn't be such problem if we used accessors from the beginning (even worst type which gives reference to innards):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
class Bar
{
public:
const int& foo() const { return foo; }
int& foo()
{
dirty = true;
return foo;
}
int bar()
{
if(dirty) {
dirty = false;
return bar_cache = do_complex_calculations(foo);
} else {
return bar_cache;
}
}
private:
int bar_cache;
bool dirty;
}
|
Simplier logic and less overhead (in actual use case dirty bytemask incurred no overhead as it was placed in padding bytes)