Does it make sense to provide non-const reference getter
Sometimes I need to expose some of the class members. For example in the following example class Mechanic
may need direct access to Engine
component. I have read many times that all fields should be accessed by mutator (accessor) methods because of several reasons. But is there any advantage when providing non-const reference getter:
class Car
{
public:
Engine & engine()
{
return m_engine;
}
//as a consequence you will also need to provide const version
const Engine & engine() const
{
return m_engine;
}
private:
Engine m_engine;
}
over simp开发者_如何学运维ly making engine component public:
class Car
{
public:
Engine engine;
}
You can also replace public
with protected
if you don't like this example. In real life you have something simillar in Java when it comes to System.in
or System.out
. It looks like, to be fully compliant on what some people say, you would need to perform calls like System.getInstance().getOut().println("hello world")
. I don't see any benefit except a lot of bureaucratic code in such cases.
They can be useful when the value you are returning is actually on the heap.
template<class T> class Singleton
{
private:
static T* m_pSingleton;
public:
T& getSingleton() { assert(m_pSingleton); return(*m_pSingleton); };
}; // eo class Singleton
Explicit getters and setters can be overly-bureaucratic; it depends on your situation.
The main cited reason for having getter and setter functions is that it isolates the clients of your class from potential changes in implementation in the future (for instance, consider what would happen if you decide to generate an Engine
object on demand (rather than using a member variable), or decide to hide it behind a smart pointer, or some other container).
If your class if very simple (e.g. close to being a POD) and unlikely to change, then it may not be worth the faff of having to implement the getters and setters.
However, to answer your question, a non-const getter probably doesn't make much sense. Your getter prototype should be Engine & engine() const
; otherwise you won't be able to call it on const
Car
objects.
One advantage of providing a getter is that when and if you decide to change the way the getter works, the code that uses this class need not be recompiled. But if you have a public field and later decide to make a getter, all code should be recompiled. Other than that I don't see any serious practical reason to make your variable private. However note that this all holds if and only if you have to provide a way for outer users to get a reference to the Engine. If it is possible to design the software so that this need be eliminated at all, that would be better.
As I happened to get educated on recently, getters and setters smell of bad design. But, if you want it that way, providing functions to get and set m_engine
(Defined by you) rather than just exposing it (You have no intervention) means that you have a plug-in point for future changes.
I have found reasonable point to provide such getter. It makes integration of your software easier (for example, when you want to translate interface into another language and bind ABIs).
For me it makes sense here:
image(i,j) = 234;
Instead of thinking about exposing private members of a class think more along the lines of calling methods on those classes. I read an interesting Java article, Why Getter and Setter Methods are Evil, which applies just as much to C++ as it does to Java.
yes, it makes sense - for maintainability, validation, and consistency.
you may need to change many aspects of the class in the future, providing an accessor can help minimize breakage of client code.
you can enter all the validation logic you need here, to ensure that engine is a valid pointer, is not in an unusable state, etc.
finally, your code will be consistent: you won't have to open the header to know the member visibility - you just always know. this is also useful with templates.
In this case you would rather need a Car.fix(const Mechanic&)
function which then gives the engine to the Mechanic
, say: Engine.fix(const Mechanic&)
, as I suppose the state of the Engine
will be modified.
The original idea of using classes was to tie together the data with its accessor functions. If you do setter or getter which merely returns an internal data, it means that your data is not tied together with its accessor functionality: your class is not complete.
You want only to expose new data which a class emits. Say Car.get_exhaust()
and the Car
does not have the exhaust, only produces it, when you ask so. ;)
Or Fire Riefle.fire()
whereas no access for Riefle::Trigger
will be fixed by the mechanic like so: Trigger.fix_by(Mechanic)
and then the fix_by
will call say Mechanic.add_working_hour(0.5)
. XD
精彩评论