C++ class template for automatic getter-setter methods - good/bad practice? -
is practice use template class objects implicit getters , setters attributes in (nearly) pod classes?
consider following template example:
template<typename t> class attribute { protected: t m_val; public: t * getaddress() { return &m_val; } t get() { return m_val; } void set(t v) { m_val = v; } };
and usage:
class { public: attribute<float> floatattr; attribute<int> intattr; attribute<long> longattr; };
with possible have encapsulated data less implementation overhead.
is bad or practice (and why)?
edit: state advantages see in this. there no need implement every getter setter function hand, there still usual advantages of these functions:
- the data encapsulated , client needs use getter setter functions, still can implemented in different way later on.
- the internal usage still hidden , can changed.
- getter , setter functions can passed around lambda functions.
in other other languages, getters , setters way of preventing implementation detail escape interface; once expose field directly, may not able later re-implement property (with getter , setter functions) without changing sites in code access field.
in c++, doesn't (so strongly) apply. can change type of field class overrides operator=
, , converts required type implicitly (for "get" side). (there of course uses doesn't apply; if pointer or reference field created in client code, example - although avoid doing , consider dubious practice).
also, because c++ statically typed, easier tools (ides etc) provide automatic refactoring, if ever need change field , corresponding accesses getter/setter pair appropriate calls.
in point of evidence, here alteration of attribute
template allows "attribute" act if directly-exposed field (except &
return address of attribute rather hidden field):
template<typename t> class attribute { protected: t m_val; public: operator t() { return m_val; } t &operator=(const t &a) { m_val = a; return m_val; } };
if really wanted to, override operator&
:
t *operator&() { return &m_val; }
... doing largely breaks encapsulation (and matter, might consider changing return type of operator=
t
or void
same reason).
if had expose field directly, replace definition instance of above template, , uses unaffected. shows why getter/setter pattern not necessary in c++.
your own solution, while encapsulates original field behind getter/setter functions, exposes field: attribute<t>
member (floatattr
etc in example). work method of encapsulation, rely on users not knowing (or caring) type of attribute field itself; is, expect no-one does:
a a; attribute<float> & float_attr = a.floatattr;
of course, if not , access fields in manner intended, indeed possible later change implementation altering type of "attribute" field:
a a; float f = a.floatattr.get();
... in sense, achieve encapsulation; real issue there better way it. :)
finally, bears mentioning both proposed attribute
template alternative show above both move field class (attribute<t>
t) separate original parent class (a
). if implementation changed, limited degree fact; attribute object not naturally have reference object contains it. example, suppose have class b
has attribute level
:
class b { public: attribute<int> level; };
now suppose later add "miminum level" field, min_level
:
class b { public: attribute<int> level; attribute<int> min_level; };
further, suppose want constrain level
, on assignment, value of min_level
. not straightforward! although can give level
new type custom implementation, not able access min_level
value containing object:
class levelattribute { int m_val; public: t &operator=(const t &a) { m_val = std::max(min_level, a); // error - min_level not defined } }
to work, you'd need pass containing object levelattribute
object, means storing pointer. typical, old-fashioned setter, declared function directly in class holds field, avoids problem.
Comments
Post a Comment