7

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 simply 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.

doc
  • 7,500
  • 5
  • 42
  • 67
  • No close vote, but if the purpose of the question is to state a theory and then disagree with all answers contrary to that theory, then it's probably "subjective and argumentative". Whether your theory is right or wrong. – Steve Jessop Nov 13 '10 at 03:07
  • @Steve Jessop: Don't be so zealous, sort questions by votes and you'll get a lot of inexact ones (question can not be subjective, the answer can be). Every answer is more or less subjective. In excuse of your your suspicions - I was on a trip and I haven't got opportunity to visit stackoverflow lately. – doc Nov 13 '10 at 11:44
  • that's why I'm uncertain. If someone is genuinely asking for reasons for something, I think that's fine even though there may be no definitive reason. If someone doesn't believe that there are any reasons, but asks for reasons anyway, I think that "usually leads to confrontation and argument". No serious harm done either way, but the latter isn't the purpose of the site AFAIK. – Steve Jessop Nov 13 '10 at 12:18
  • Related: [Why do people write private-field getters returning a non-const reference?](https://stackoverflow.com/questions/42587067/why-do-people-write-private-field-getters-returning-a-non-const-reference) – sergiol Mar 21 '18 at 18:36
  • Related: [Breaking encapsulation by returning non-const references to members](https://stackoverflow.com/questions/36855426/breaking-encapsulation-by-returning-non-const-references-to-members#comment86816406_36855426) – sergiol Apr 20 '18 at 11:34
  • Here is a Regex for Visual Studio which may help find cases of methods returning non-const references: `(?]*>\s*)*&\s+\w+(?:::\w+)*\s*\(` — May be not perfect, someone can suggest improvements! – sergiol Apr 20 '18 at 11:35

9 Answers9

3

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
Moo-Juice
  • 36,340
  • 10
  • 69
  • 121
  • 3
    Definitely downvoting for the Singleton pattern. – Puppy Nov 06 '10 at 16:23
  • 2
    Ah, I remember the times when the Singleton pattern was all the rage... Heck, I even remember when PEEK and POKE was all the rage. :-) –  Nov 06 '10 at 17:54
  • 4
    Yeah, arrays are evil, getters and setters are evil, singletons are evil, whole programming is evil. Best programmers are those who didn't write a piece of code. +1 because singletons are sometimes useful. – doc Nov 06 '10 at 21:33
3

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.

Oliver Charlesworth
  • 252,669
  • 29
  • 530
  • 650
  • 2
    For better googling, this is called *encapsulation*. – Björn Pollex Nov 06 '10 at 16:07
  • 1
    I have fixed the example. There shall be two versions of `engine()` method: const and non-const. In my opinion sometimes it's convenient to expose members and draw back encapsulation. – doc Nov 06 '10 at 16:13
1

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.

Armen Tsirunyan
  • 120,726
  • 52
  • 304
  • 418
  • 1
    If you provide a field, and later change to a getter, client code doesn't just have to be recompiled, it has to be rewritten. – Steve Jessop Nov 08 '10 at 01:19
1

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.

nakiya
  • 12,981
  • 20
  • 67
  • 111
  • How can you implement, let's say, `class Window` with its width, height, and some other properties without getters nor setters? Aren't we going mad? Most real life object are like `class Window`; almost plain structures filled with some methods. I have met design with few accesors (although `Window` has got its `GetWidth` or `GetSize` methods) in the form of SFML library and because of that I was not able to extend its classes nicely. – doc Nov 06 '10 at 21:44
  • There were two points in my answer. The first is : Encapsulation is good. The second is, if you can't have the first, then getters and setters are good. The idea in the second scenario is to avoid code duplication that may happen in the future(Or right now) if you want to enforce some constraint on `Window`s width or height. On the first point, while setters can be excused a little, why do you need getters? Doesn't that mean that you'd rather have that bit of data the getter is exposing outside? If it is in the class, why let others tamper with it (Why even provide const getters)? – nakiya Nov 07 '10 at 12:03
  • In your question, what you should do is pass an object of `Mechanic` to a `Car` object so that the `Car` object can pass its `Engine` object to the `Mechanic` object. This way, you eliminate the getter and a `Terrorist` will not be able to access the engine of a `Car`. – nakiya Nov 07 '10 at 12:08
  • 1
    Check this (Which I asked a couple of weeks back) : http://stackoverflow.com/questions/3933006/is-it-good-practice-to-make-member-variables-protected and this : http://www.idinews.com/quasiClass.pdf out. Should convert you :). – nakiya Nov 07 '10 at 12:17
  • @nakiya: Encapsulation is about hiding implementation details, not about getters, setters, whatever. You can have no getter nor setter and still brake encapsulation! On the other hand, if you will not provide all the necessary pieces of your class, then someone may be not able to extend this class nicely and this is also wrong. – doc Nov 13 '10 at 12:45
  • @nakiya: my intention is that `Terrorist` should also have an access to `Engine` component. It's loosely binded component. – doc Nov 13 '10 at 12:50
  • @doc: My point wasn't that getters and setters are bad **always**. it was just that I see the whole point in making one class do one specific thing well. Which means generally a class should not let others tamper with its inner data. If your class lets others do this, that means that it's data is not its own- which, you should be able to understand, is not very beautiful. And, on your second answer, `Terrorist` actually does have access to `Engine` is this universe with its laws. That does not mean its the best rules. Depending on whether you are a `Terrorist` or not. – nakiya Nov 15 '10 at 18:21
  • @nakiya: But I need to model this imperfect world and not to invent a perfect one. – doc Nov 26 '10 at 17:07
1

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).

doc
  • 7,500
  • 5
  • 42
  • 67
0

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

Barney Szabolcs
  • 10,339
  • 9
  • 55
  • 80
0

For me it makes sense here:

image(i,j) = 234;
log0
  • 9,642
  • 2
  • 23
  • 59
0

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.

Tony
  • 8,904
  • 3
  • 41
  • 67
  • Yes I have read that and wrote the comment titled "Theory is just theory" :) My point is that code consists of operations and data, not only the code. Somehow you have to modify the data so the article is obviously wrong. The author doesn't see the big picture behind computing. He has stucked into some principles built on the top of it, called Object Oriented Programming. But OOP doesn't exist without procedural programming. – doc Nov 06 '10 at 16:25
  • @doc: If it is useless, why worry about what theory says in the first place? In regards to computer patterns, theory is not some abstract mathematical concept that some daydreamer conjures up (Read "Head first design patterns" on this). They are born out of necessity (Due to problems faced in practice). Your problem is one of them. So when someone says "Getters and setters are evil", it's not like saying "1 == 1". – nakiya Nov 07 '10 at 14:48
0

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.

justin
  • 101,751
  • 13
  • 172
  • 222