Quote:Original post by maximAL
shocking how many people give stupid advises about setters/getters [rolleyes]
for one, they indeed hide the implementation, because sometimes you might calculate the get-value on the fly instead of straight accesing a variable, respectively spread the set-value over various values.
and even if you don't need that (read: your'e the 1337 hax0r and never change your ingenious design) accessors are the only way to implement save value-checks (assertions, exceptions...).
template < typename scalar_t , scalar_t min , scalar_t max >class bounded_scalar { scalar_t value;public: typedef bounded_scalar< scalar_t , min , max > self_type; self_type & operator=( scalar_t new_value ) { assert( new_value >= min ); assert( new_value <= max ); value = new_value; return *this; } ...};struct rgb_color { bounded_scalar< double , 0.0 , 1.0 > red, green, blue;};
This is not an argument for or against public data (although I swing towards the extreme end of the "for it" camp). This is merely part of a limited example of delegating responsibility to a subclass in such a manner that any/all of the correctness checking responsibility of the owner is lifted, thus allowing our data to become public while still mantaining all the appropriate invariants (in this case, that 0.0 <= component <= 1.0).
BBB: 1) m_member m_prefixes m_are m_usually m_reserved m_for m_member m_variables m_rather m_than m_every m_function m_you m_can m_tack m_them m_onto. m_Also, m_it's m_pretty m_obvious m_they're m_members, m_just m_like m_it's m_obvious m_these m_are m_all m_words. m_In m_my m_opinion, m_anyways,
2) This approach has flaws the moment you need to check/modify something else in the class. You have two options:
a) Your syntax breaks:
foo.bar.set( 3 ); becomes foo.set_bar( 3 );
b) Your sub-member gets a pointer to foo (extra data):
class Bar { Foo * parent; int v;public: Bar( Foo * parent ) : parent( parent ) { } void Set( int new_v ) { assert( parent->baz == 13 ); v = new_v; }};
3) The entire point of the get/set pattern is to avoid these two problems.
4) If potentially having these problems in the future is okay with you, you might as well simply use assignment syntax:
foo.bar = 3;
5) This will have the exact same drawbacks as listed above:
a) Break syntax (when extra checking needed):
foo.bar = 3; becomes foo.set_bar( 3 );
b) Add a pointer to "this":
class Bar { Foo * parent; int v;public: Bar( Foo * parent ) : parent( parent ) {} Bar & operator=( int new_v ) { assert( parent->baz == 13 ); v = new_v; return *this; }};
Please note the extreme similarity between this and the previous example. You're doing the exact same amount of work.
6) Given that assignment syntax is:
*) slightly clearer (at least when dealing with nonsense values such as foo and bar)
*) easier to implement with no checking (just make the variable public)
*) the same amount of work if you want to break things after the fact
I cannot recommend your example.
This isn't even delving into how assine I consider "get/set everything" to be.