Reasons for defining non-const 'get' member functions?












21














I'm working on learning C++ with Stroustrup's (Programming Principles & Practice Using C++) book. In an exercise we define a simple struct:



template<typename T>
struct S {
explicit S(T v):val{v} { };

T& get();
const T& get() const;

void set(T v);
void read_val(T& v);

T& operator=(const T& t); // deep copy assignment

private:
T val;
};


We're then asked to define a const and a non-const member function to get val.



I was wondering: Is there any case where it makes sense to have non-const get function that returns val?



It seems much cleaner to me that we can't change the value in such situations indirectly. What might be use cases where you need a const and a non-const get function to return a member variable?










share|improve this question


















  • 9




    IMO even cleaner would be no getters or setters at all, and instead have the class be about behavior instead. If you have getters and setters for a member variable, you might as well make it public.
    – Some programmer dude
    Dec 8 at 13:40






  • 1




    The primary reason for using a non-const get member function (or any getter and setter anti-pattern) is to avoid doing proper object-oriented programming.
    – Eljay
    Dec 8 at 14:16








  • 2




    @Someprogrammerdude Not really. Maybe right now that field is just a plain value but you know that when you are going to iterate to develop new requirements it will have to be a computed value, and thus having a getter avoids having to change all the code that accesses the field. Also: having a getter you can easily add a breakpoint on it and check in a debugger where is the code that accesses it. If you have just a field you have to put breakpoints in every place that accesses the field which is much more cumbersome to do.
    – Bakuriu
    Dec 8 at 14:49










  • A const getter makes sense if the setter had to make some checks (i.e. establish invariants) before setting the value which, in cases when it needs an invariant, is usually made private to allow modification through a constructor and a setter only (which would guarantee the invariants). In general, in my experience setters and getters, and especially non-const getters, are more often a result of oral and written tradition rather than a conclusion of thoughts specific to a particular case. However, notice that Stroustrup's example is a generic case meant to simply introduce the idea.
    – Leo Heinsaar
    Dec 9 at 11:22












  • @Bakuriu I guess what Some was refering to is that other classes accessing private fields is bad design in the first place. Just a stupid example: bad design is to have a customer::getMoney() and customer::setMoney(int) when it actually should be a customer::pay(int). All your concerns are covered by pay plus you dont break encapsulation
    – user463035818
    Dec 13 at 12:21


















21














I'm working on learning C++ with Stroustrup's (Programming Principles & Practice Using C++) book. In an exercise we define a simple struct:



template<typename T>
struct S {
explicit S(T v):val{v} { };

T& get();
const T& get() const;

void set(T v);
void read_val(T& v);

T& operator=(const T& t); // deep copy assignment

private:
T val;
};


We're then asked to define a const and a non-const member function to get val.



I was wondering: Is there any case where it makes sense to have non-const get function that returns val?



It seems much cleaner to me that we can't change the value in such situations indirectly. What might be use cases where you need a const and a non-const get function to return a member variable?










share|improve this question


















  • 9




    IMO even cleaner would be no getters or setters at all, and instead have the class be about behavior instead. If you have getters and setters for a member variable, you might as well make it public.
    – Some programmer dude
    Dec 8 at 13:40






  • 1




    The primary reason for using a non-const get member function (or any getter and setter anti-pattern) is to avoid doing proper object-oriented programming.
    – Eljay
    Dec 8 at 14:16








  • 2




    @Someprogrammerdude Not really. Maybe right now that field is just a plain value but you know that when you are going to iterate to develop new requirements it will have to be a computed value, and thus having a getter avoids having to change all the code that accesses the field. Also: having a getter you can easily add a breakpoint on it and check in a debugger where is the code that accesses it. If you have just a field you have to put breakpoints in every place that accesses the field which is much more cumbersome to do.
    – Bakuriu
    Dec 8 at 14:49










  • A const getter makes sense if the setter had to make some checks (i.e. establish invariants) before setting the value which, in cases when it needs an invariant, is usually made private to allow modification through a constructor and a setter only (which would guarantee the invariants). In general, in my experience setters and getters, and especially non-const getters, are more often a result of oral and written tradition rather than a conclusion of thoughts specific to a particular case. However, notice that Stroustrup's example is a generic case meant to simply introduce the idea.
    – Leo Heinsaar
    Dec 9 at 11:22












  • @Bakuriu I guess what Some was refering to is that other classes accessing private fields is bad design in the first place. Just a stupid example: bad design is to have a customer::getMoney() and customer::setMoney(int) when it actually should be a customer::pay(int). All your concerns are covered by pay plus you dont break encapsulation
    – user463035818
    Dec 13 at 12:21
















21












21








21


1





I'm working on learning C++ with Stroustrup's (Programming Principles & Practice Using C++) book. In an exercise we define a simple struct:



template<typename T>
struct S {
explicit S(T v):val{v} { };

T& get();
const T& get() const;

void set(T v);
void read_val(T& v);

T& operator=(const T& t); // deep copy assignment

private:
T val;
};


We're then asked to define a const and a non-const member function to get val.



I was wondering: Is there any case where it makes sense to have non-const get function that returns val?



It seems much cleaner to me that we can't change the value in such situations indirectly. What might be use cases where you need a const and a non-const get function to return a member variable?










share|improve this question













I'm working on learning C++ with Stroustrup's (Programming Principles & Practice Using C++) book. In an exercise we define a simple struct:



template<typename T>
struct S {
explicit S(T v):val{v} { };

T& get();
const T& get() const;

void set(T v);
void read_val(T& v);

T& operator=(const T& t); // deep copy assignment

private:
T val;
};


We're then asked to define a const and a non-const member function to get val.



I was wondering: Is there any case where it makes sense to have non-const get function that returns val?



It seems much cleaner to me that we can't change the value in such situations indirectly. What might be use cases where you need a const and a non-const get function to return a member variable?







c++ const getter member-functions






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Dec 8 at 13:35









Juri

16812




16812








  • 9




    IMO even cleaner would be no getters or setters at all, and instead have the class be about behavior instead. If you have getters and setters for a member variable, you might as well make it public.
    – Some programmer dude
    Dec 8 at 13:40






  • 1




    The primary reason for using a non-const get member function (or any getter and setter anti-pattern) is to avoid doing proper object-oriented programming.
    – Eljay
    Dec 8 at 14:16








  • 2




    @Someprogrammerdude Not really. Maybe right now that field is just a plain value but you know that when you are going to iterate to develop new requirements it will have to be a computed value, and thus having a getter avoids having to change all the code that accesses the field. Also: having a getter you can easily add a breakpoint on it and check in a debugger where is the code that accesses it. If you have just a field you have to put breakpoints in every place that accesses the field which is much more cumbersome to do.
    – Bakuriu
    Dec 8 at 14:49










  • A const getter makes sense if the setter had to make some checks (i.e. establish invariants) before setting the value which, in cases when it needs an invariant, is usually made private to allow modification through a constructor and a setter only (which would guarantee the invariants). In general, in my experience setters and getters, and especially non-const getters, are more often a result of oral and written tradition rather than a conclusion of thoughts specific to a particular case. However, notice that Stroustrup's example is a generic case meant to simply introduce the idea.
    – Leo Heinsaar
    Dec 9 at 11:22












  • @Bakuriu I guess what Some was refering to is that other classes accessing private fields is bad design in the first place. Just a stupid example: bad design is to have a customer::getMoney() and customer::setMoney(int) when it actually should be a customer::pay(int). All your concerns are covered by pay plus you dont break encapsulation
    – user463035818
    Dec 13 at 12:21
















  • 9




    IMO even cleaner would be no getters or setters at all, and instead have the class be about behavior instead. If you have getters and setters for a member variable, you might as well make it public.
    – Some programmer dude
    Dec 8 at 13:40






  • 1




    The primary reason for using a non-const get member function (or any getter and setter anti-pattern) is to avoid doing proper object-oriented programming.
    – Eljay
    Dec 8 at 14:16








  • 2




    @Someprogrammerdude Not really. Maybe right now that field is just a plain value but you know that when you are going to iterate to develop new requirements it will have to be a computed value, and thus having a getter avoids having to change all the code that accesses the field. Also: having a getter you can easily add a breakpoint on it and check in a debugger where is the code that accesses it. If you have just a field you have to put breakpoints in every place that accesses the field which is much more cumbersome to do.
    – Bakuriu
    Dec 8 at 14:49










  • A const getter makes sense if the setter had to make some checks (i.e. establish invariants) before setting the value which, in cases when it needs an invariant, is usually made private to allow modification through a constructor and a setter only (which would guarantee the invariants). In general, in my experience setters and getters, and especially non-const getters, are more often a result of oral and written tradition rather than a conclusion of thoughts specific to a particular case. However, notice that Stroustrup's example is a generic case meant to simply introduce the idea.
    – Leo Heinsaar
    Dec 9 at 11:22












  • @Bakuriu I guess what Some was refering to is that other classes accessing private fields is bad design in the first place. Just a stupid example: bad design is to have a customer::getMoney() and customer::setMoney(int) when it actually should be a customer::pay(int). All your concerns are covered by pay plus you dont break encapsulation
    – user463035818
    Dec 13 at 12:21










9




9




IMO even cleaner would be no getters or setters at all, and instead have the class be about behavior instead. If you have getters and setters for a member variable, you might as well make it public.
– Some programmer dude
Dec 8 at 13:40




IMO even cleaner would be no getters or setters at all, and instead have the class be about behavior instead. If you have getters and setters for a member variable, you might as well make it public.
– Some programmer dude
Dec 8 at 13:40




1




1




The primary reason for using a non-const get member function (or any getter and setter anti-pattern) is to avoid doing proper object-oriented programming.
– Eljay
Dec 8 at 14:16






The primary reason for using a non-const get member function (or any getter and setter anti-pattern) is to avoid doing proper object-oriented programming.
– Eljay
Dec 8 at 14:16






2




2




@Someprogrammerdude Not really. Maybe right now that field is just a plain value but you know that when you are going to iterate to develop new requirements it will have to be a computed value, and thus having a getter avoids having to change all the code that accesses the field. Also: having a getter you can easily add a breakpoint on it and check in a debugger where is the code that accesses it. If you have just a field you have to put breakpoints in every place that accesses the field which is much more cumbersome to do.
– Bakuriu
Dec 8 at 14:49




@Someprogrammerdude Not really. Maybe right now that field is just a plain value but you know that when you are going to iterate to develop new requirements it will have to be a computed value, and thus having a getter avoids having to change all the code that accesses the field. Also: having a getter you can easily add a breakpoint on it and check in a debugger where is the code that accesses it. If you have just a field you have to put breakpoints in every place that accesses the field which is much more cumbersome to do.
– Bakuriu
Dec 8 at 14:49












A const getter makes sense if the setter had to make some checks (i.e. establish invariants) before setting the value which, in cases when it needs an invariant, is usually made private to allow modification through a constructor and a setter only (which would guarantee the invariants). In general, in my experience setters and getters, and especially non-const getters, are more often a result of oral and written tradition rather than a conclusion of thoughts specific to a particular case. However, notice that Stroustrup's example is a generic case meant to simply introduce the idea.
– Leo Heinsaar
Dec 9 at 11:22






A const getter makes sense if the setter had to make some checks (i.e. establish invariants) before setting the value which, in cases when it needs an invariant, is usually made private to allow modification through a constructor and a setter only (which would guarantee the invariants). In general, in my experience setters and getters, and especially non-const getters, are more often a result of oral and written tradition rather than a conclusion of thoughts specific to a particular case. However, notice that Stroustrup's example is a generic case meant to simply introduce the idea.
– Leo Heinsaar
Dec 9 at 11:22














@Bakuriu I guess what Some was refering to is that other classes accessing private fields is bad design in the first place. Just a stupid example: bad design is to have a customer::getMoney() and customer::setMoney(int) when it actually should be a customer::pay(int). All your concerns are covered by pay plus you dont break encapsulation
– user463035818
Dec 13 at 12:21






@Bakuriu I guess what Some was refering to is that other classes accessing private fields is bad design in the first place. Just a stupid example: bad design is to have a customer::getMoney() and customer::setMoney(int) when it actually should be a customer::pay(int). All your concerns are covered by pay plus you dont break encapsulation
– user463035818
Dec 13 at 12:21














6 Answers
6






active

oldest

votes


















15














Non-const getters?



Getters and setters are merely convention. Instead of providing a getter and a setter, a sometimes used idiom is to provide something along the line of



struct foo {
int val() const { return val_; }
int& val() { return val_; }
private:
int val_;
};


Such that, depending on the constness of the instance you get a reference or a copy:



void bar(const foo& a, foo& b) {
auto x = a.val(); // calls the const method returning an int
b.val() = x; // calls the non-const method returning an int&
};


Whether this is good style in general is a matter of opinion. There are cases where it causes confusion and other cases where this behaviour is just what you would expect (see below).



In any case, it is more important to design the interface of a class according to what the class is supposed to do and how you want to use it rather than blindly following conventions about setters and getters (eg you should give the method a meaningful name that expresses what it does, not just in terms of "pretend to be encapsulated and now provide me access to all your internals via getters", which is what using getters everywhere actually means).



Concrete example



Consider that element access in containers is usually implemented like this. As a toy example:



struct my_array {
int operator(unsigned i) const { return data[i]; }
int& operator(unsigned i) { return data[i]; }
private:
int data[10];
};


It is not the containers job to hide the elements from the user (even data could be public). You dont want different methods to access elements depending on whether you want to read or write the element, hence providing a const and a non-const overload makes perfectly sense in this case.



non-const reference from get vs encapsulation



Maybe not that obvious, but it is a bit controversial whether providing getters and setters supports encapsulation or the opposite. While in general this matter is to a large extend opinion based, for getters that return non const references it is not so much about opinions. They do break encapuslation. Consider



struct broken {
void set(int x) {
counter++;
val = x;
}
int& get() { return x; }
int get() const { return x; }
private:
int counter = 0;
int value = 0;
};


This class is broken as the name suggests. Clients can simply grab a reference and the class has no chance to count the number of times the value is modified (as the set suggests). Once you return a non-const reference then regarding encapsulation there is little difference to making the member public. Hence, this is used only for cases where such behaviour is natural (eg container).



PS



Note that your example returns a const T& rather than a value. This is reasonable for template code, where you dont know how expensive a copy is, while for an int you wont gain much by returning a const int& instead of an int. For the sake of clarity I used non-template examples, though for templated code you would probably rather return a const T&.






share|improve this answer































    8














    First let me rephrase your question:




    Why have a non-const getter for a member, rather than just making the member public?




    Several possible reasons reasons:



    1. Easy to instrument



    Who said the non-const getter needs to be just:



        T& get() { return val; }


    ? it could well be something like:



        T& get() { 
    if (check_for_something_bad()) {
    throw std::runtime_error{"Attempt to mutate val when bad things have happened");
    }
    return val;
    }

    However, as @BenVoigt suggests, it is more appropriate to wait until the caller actually tries to mutate the value through the reference before spewing an error.


    2. Cultural convention / "the boss said so"



    Some organizations enforce coding standards. These coding standards are sometimes authored by people who are possibly overly-defensive. So, you might see something like:




    Unless your class is a "plain old data" type, no data members may be public. You may use getter methods for such non-public members as necessary.




    and then, even if it makes sense for a specific class to just allow non-const access, it won't happen.



    3. Maybe val just isn't there?



    You've given an example in which val actually exists in an instance of the class. But actually - it doesn't have to! The get() method could return some sort of a proxy object, which, upon assignment, mutation etc. performs some computation (e.g. storing or retrieving data in a database).



    4. Allows changing class internals later without changing user code



    Now, reading items 1. or 3, above, you might ask "but my struct S does have val!" or "by my get() doesn't do anything interesting!" - well, true, they don't; but you might want to change this behavior in the future. Without a get(), all of your class' users will need to change their code. With a get(), you only need to make changes to the implementation of struct S.



    Now, I don't advocate for this kind of a design approach approach, but some programmers do.






    share|improve this answer



















    • 1




      "Attempt to mutate val when bad things have happened" is just incorrect. Selection of const or non-const member function depends on the qualifications of the this object, and not how the return value is being used. In particular, a non-const getter cannot assume mutation is occurring.
      – Ben Voigt
      Dec 9 at 0:48










    • @BenVoigt: Suppose S is something NuclearMissilePosition, or PatientInfusionValueState. These are mutable, and should be mutable, but under certain conditions I might not want . Now, you could say "ok, only let friend functions mutate them then", or "write a setter function then", but this is also a way to do it.
      – einpoklum
      Dec 9 at 10:42










    • But when you cannot distinguish between get and set, your error message should reflect that uncertainty, not claim mutation was attempted.
      – Ben Voigt
      Dec 10 at 0:30










    • Ok, fair enough.
      – einpoklum
      Dec 11 at 15:46



















    5














    get() is callable by non const objects which are allowed to mutate, you can do:



    S r(0);
    r.get() = 1;


    but if you make r const as const S r(0), the line r.get() = 1 no longer compile, not even to retrieve the value, that's why you need a const version const T& get() const to at least to able to retrieve the value for const objects, doing so allows you do:



    const S r(0)
    int val = r.get()


    The const version of member functions try to be consistent with the constness property of the object the call is made on, i.e if the object is immutable by being const and the member function returns a reference, it may reflect the constness of the caller by returning a const reference, thus preserving the immutability property of the object.






    share|improve this answer



















    • 1




      OP was asking, I'm sure, why have this method rather than just giving access to the member itself.
      – einpoklum
      Dec 8 at 14:13






    • 1




      @einpoklum He was more interested in the reason and uses cases of having two different versions of get to perform the same action "return val" ... check at his last 2 paragraphs.
      – Jans
      Dec 8 at 14:17



















    3














    It depends on the purpose of S. If it's some kind of a thin wrapper, it might be appropriate to allow the user to access the underlaying value directly.



    One of the real-life examples is std::reference_wrapper.






    share|improve this answer





















    • This is likely the "spot on" answer. Useful when encapsulating C types for external libraries and such.
      – pipe
      Dec 8 at 17:16










    • In my opinion, reference_wrapper does a different thing. In OP's example, with get(), you can modify the value of the member. With reference_wrapper::get, you cannot modify which object it points to, you can only modify the pointed object.
      – geza
      Dec 8 at 20:20










    • @geza reference_wrapper exposes reference semantics, so its "value" is the wrapped object. The fact it's hold by pointer is just an implementation detail.
      – Igor R.
      Dec 8 at 21:29










    • That's why it is not relevant here. In OP's example, get() returns a reference to a member, which is contained within the object. reference_wrapper doesn't do this., its get() function does something else. "Is there any case where it makes sense to have non-const get function that returns val?". reference_wrapper returns the value pointed to, not the value itself.
      – geza
      Dec 8 at 21:36



















    1














    No. If a getter simply returns a non-const reference to a member, like this:



    private:
    Object m_member;

    public:
    Object &getMember() {
    return m_member;
    }


    Then m_member should be public instead, and the accessor is not needed. There is absolutely no point making this member private, and then create an accessor, which gives all access to it.



    If you call getMember(), you can store the resulting reference to a pointer/reference, and afterwards, you can do whatever you want with m_member, the enclosing class will know nothing about it. It's the same, as if m_member had been public.



    Note, that if getMember() does some additional task (for example, it doesn't just simply return m_member, but lazily constructs it), then getMember() could be useful:



    Object &getMember() {
    if (!m_member) m_member = new Object;
    return *m_member;
    }





    share|improve this answer





























      0














      I would also like to point out the practical side of the question. For example, you want to aggregate your object Bar into another object Foo and create constant method doSomething which uses Bar only for reading:



      class Foo
      {
      Bar bar_;
      public:
      void doSomething() const
      {
      //bar_.get();
      }
      }


      You have a problem! You are absolutely sure that you do not change the Foo object, you want to mark this by const modificator, but you cannot do it, because get is not const. In other words, you create your own problems for the future and complicate the writing of clear and high-quality code. But you can implement two versions for get if you really need it:



      class Bar
      {
      int data = 1;
      public:
      int& get() { return data; };
      const int& get() const { return data; };
      };


      such a situation can arise if you ALREADY have a code in which constant modifiers are ignored, therefore such a situation is common:



      foo(int* a); // Just get a, don`t modified
      foo(&bar_.get()); // need non constant get()





      share|improve this answer























        Your Answer






        StackExchange.ifUsing("editor", function () {
        StackExchange.using("externalEditor", function () {
        StackExchange.using("snippets", function () {
        StackExchange.snippets.init();
        });
        });
        }, "code-snippets");

        StackExchange.ready(function() {
        var channelOptions = {
        tags: "".split(" "),
        id: "1"
        };
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function() {
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled) {
        StackExchange.using("snippets", function() {
        createEditor();
        });
        }
        else {
        createEditor();
        }
        });

        function createEditor() {
        StackExchange.prepareEditor({
        heartbeatType: 'answer',
        autoActivateHeartbeat: false,
        convertImagesToLinks: true,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: 10,
        bindNavPrevention: true,
        postfix: "",
        imageUploader: {
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        },
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        });


        }
        });














        draft saved

        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53683047%2freasons-for-defining-non-const-get-member-functions%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        6 Answers
        6






        active

        oldest

        votes








        6 Answers
        6






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        15














        Non-const getters?



        Getters and setters are merely convention. Instead of providing a getter and a setter, a sometimes used idiom is to provide something along the line of



        struct foo {
        int val() const { return val_; }
        int& val() { return val_; }
        private:
        int val_;
        };


        Such that, depending on the constness of the instance you get a reference or a copy:



        void bar(const foo& a, foo& b) {
        auto x = a.val(); // calls the const method returning an int
        b.val() = x; // calls the non-const method returning an int&
        };


        Whether this is good style in general is a matter of opinion. There are cases where it causes confusion and other cases where this behaviour is just what you would expect (see below).



        In any case, it is more important to design the interface of a class according to what the class is supposed to do and how you want to use it rather than blindly following conventions about setters and getters (eg you should give the method a meaningful name that expresses what it does, not just in terms of "pretend to be encapsulated and now provide me access to all your internals via getters", which is what using getters everywhere actually means).



        Concrete example



        Consider that element access in containers is usually implemented like this. As a toy example:



        struct my_array {
        int operator(unsigned i) const { return data[i]; }
        int& operator(unsigned i) { return data[i]; }
        private:
        int data[10];
        };


        It is not the containers job to hide the elements from the user (even data could be public). You dont want different methods to access elements depending on whether you want to read or write the element, hence providing a const and a non-const overload makes perfectly sense in this case.



        non-const reference from get vs encapsulation



        Maybe not that obvious, but it is a bit controversial whether providing getters and setters supports encapsulation or the opposite. While in general this matter is to a large extend opinion based, for getters that return non const references it is not so much about opinions. They do break encapuslation. Consider



        struct broken {
        void set(int x) {
        counter++;
        val = x;
        }
        int& get() { return x; }
        int get() const { return x; }
        private:
        int counter = 0;
        int value = 0;
        };


        This class is broken as the name suggests. Clients can simply grab a reference and the class has no chance to count the number of times the value is modified (as the set suggests). Once you return a non-const reference then regarding encapsulation there is little difference to making the member public. Hence, this is used only for cases where such behaviour is natural (eg container).



        PS



        Note that your example returns a const T& rather than a value. This is reasonable for template code, where you dont know how expensive a copy is, while for an int you wont gain much by returning a const int& instead of an int. For the sake of clarity I used non-template examples, though for templated code you would probably rather return a const T&.






        share|improve this answer




























          15














          Non-const getters?



          Getters and setters are merely convention. Instead of providing a getter and a setter, a sometimes used idiom is to provide something along the line of



          struct foo {
          int val() const { return val_; }
          int& val() { return val_; }
          private:
          int val_;
          };


          Such that, depending on the constness of the instance you get a reference or a copy:



          void bar(const foo& a, foo& b) {
          auto x = a.val(); // calls the const method returning an int
          b.val() = x; // calls the non-const method returning an int&
          };


          Whether this is good style in general is a matter of opinion. There are cases where it causes confusion and other cases where this behaviour is just what you would expect (see below).



          In any case, it is more important to design the interface of a class according to what the class is supposed to do and how you want to use it rather than blindly following conventions about setters and getters (eg you should give the method a meaningful name that expresses what it does, not just in terms of "pretend to be encapsulated and now provide me access to all your internals via getters", which is what using getters everywhere actually means).



          Concrete example



          Consider that element access in containers is usually implemented like this. As a toy example:



          struct my_array {
          int operator(unsigned i) const { return data[i]; }
          int& operator(unsigned i) { return data[i]; }
          private:
          int data[10];
          };


          It is not the containers job to hide the elements from the user (even data could be public). You dont want different methods to access elements depending on whether you want to read or write the element, hence providing a const and a non-const overload makes perfectly sense in this case.



          non-const reference from get vs encapsulation



          Maybe not that obvious, but it is a bit controversial whether providing getters and setters supports encapsulation or the opposite. While in general this matter is to a large extend opinion based, for getters that return non const references it is not so much about opinions. They do break encapuslation. Consider



          struct broken {
          void set(int x) {
          counter++;
          val = x;
          }
          int& get() { return x; }
          int get() const { return x; }
          private:
          int counter = 0;
          int value = 0;
          };


          This class is broken as the name suggests. Clients can simply grab a reference and the class has no chance to count the number of times the value is modified (as the set suggests). Once you return a non-const reference then regarding encapsulation there is little difference to making the member public. Hence, this is used only for cases where such behaviour is natural (eg container).



          PS



          Note that your example returns a const T& rather than a value. This is reasonable for template code, where you dont know how expensive a copy is, while for an int you wont gain much by returning a const int& instead of an int. For the sake of clarity I used non-template examples, though for templated code you would probably rather return a const T&.






          share|improve this answer


























            15












            15








            15






            Non-const getters?



            Getters and setters are merely convention. Instead of providing a getter and a setter, a sometimes used idiom is to provide something along the line of



            struct foo {
            int val() const { return val_; }
            int& val() { return val_; }
            private:
            int val_;
            };


            Such that, depending on the constness of the instance you get a reference or a copy:



            void bar(const foo& a, foo& b) {
            auto x = a.val(); // calls the const method returning an int
            b.val() = x; // calls the non-const method returning an int&
            };


            Whether this is good style in general is a matter of opinion. There are cases where it causes confusion and other cases where this behaviour is just what you would expect (see below).



            In any case, it is more important to design the interface of a class according to what the class is supposed to do and how you want to use it rather than blindly following conventions about setters and getters (eg you should give the method a meaningful name that expresses what it does, not just in terms of "pretend to be encapsulated and now provide me access to all your internals via getters", which is what using getters everywhere actually means).



            Concrete example



            Consider that element access in containers is usually implemented like this. As a toy example:



            struct my_array {
            int operator(unsigned i) const { return data[i]; }
            int& operator(unsigned i) { return data[i]; }
            private:
            int data[10];
            };


            It is not the containers job to hide the elements from the user (even data could be public). You dont want different methods to access elements depending on whether you want to read or write the element, hence providing a const and a non-const overload makes perfectly sense in this case.



            non-const reference from get vs encapsulation



            Maybe not that obvious, but it is a bit controversial whether providing getters and setters supports encapsulation or the opposite. While in general this matter is to a large extend opinion based, for getters that return non const references it is not so much about opinions. They do break encapuslation. Consider



            struct broken {
            void set(int x) {
            counter++;
            val = x;
            }
            int& get() { return x; }
            int get() const { return x; }
            private:
            int counter = 0;
            int value = 0;
            };


            This class is broken as the name suggests. Clients can simply grab a reference and the class has no chance to count the number of times the value is modified (as the set suggests). Once you return a non-const reference then regarding encapsulation there is little difference to making the member public. Hence, this is used only for cases where such behaviour is natural (eg container).



            PS



            Note that your example returns a const T& rather than a value. This is reasonable for template code, where you dont know how expensive a copy is, while for an int you wont gain much by returning a const int& instead of an int. For the sake of clarity I used non-template examples, though for templated code you would probably rather return a const T&.






            share|improve this answer














            Non-const getters?



            Getters and setters are merely convention. Instead of providing a getter and a setter, a sometimes used idiom is to provide something along the line of



            struct foo {
            int val() const { return val_; }
            int& val() { return val_; }
            private:
            int val_;
            };


            Such that, depending on the constness of the instance you get a reference or a copy:



            void bar(const foo& a, foo& b) {
            auto x = a.val(); // calls the const method returning an int
            b.val() = x; // calls the non-const method returning an int&
            };


            Whether this is good style in general is a matter of opinion. There are cases where it causes confusion and other cases where this behaviour is just what you would expect (see below).



            In any case, it is more important to design the interface of a class according to what the class is supposed to do and how you want to use it rather than blindly following conventions about setters and getters (eg you should give the method a meaningful name that expresses what it does, not just in terms of "pretend to be encapsulated and now provide me access to all your internals via getters", which is what using getters everywhere actually means).



            Concrete example



            Consider that element access in containers is usually implemented like this. As a toy example:



            struct my_array {
            int operator(unsigned i) const { return data[i]; }
            int& operator(unsigned i) { return data[i]; }
            private:
            int data[10];
            };


            It is not the containers job to hide the elements from the user (even data could be public). You dont want different methods to access elements depending on whether you want to read or write the element, hence providing a const and a non-const overload makes perfectly sense in this case.



            non-const reference from get vs encapsulation



            Maybe not that obvious, but it is a bit controversial whether providing getters and setters supports encapsulation or the opposite. While in general this matter is to a large extend opinion based, for getters that return non const references it is not so much about opinions. They do break encapuslation. Consider



            struct broken {
            void set(int x) {
            counter++;
            val = x;
            }
            int& get() { return x; }
            int get() const { return x; }
            private:
            int counter = 0;
            int value = 0;
            };


            This class is broken as the name suggests. Clients can simply grab a reference and the class has no chance to count the number of times the value is modified (as the set suggests). Once you return a non-const reference then regarding encapsulation there is little difference to making the member public. Hence, this is used only for cases where such behaviour is natural (eg container).



            PS



            Note that your example returns a const T& rather than a value. This is reasonable for template code, where you dont know how expensive a copy is, while for an int you wont gain much by returning a const int& instead of an int. For the sake of clarity I used non-template examples, though for templated code you would probably rather return a const T&.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Dec 13 at 19:55

























            answered Dec 8 at 13:43









            user463035818

            16.5k42663




            16.5k42663

























                8














                First let me rephrase your question:




                Why have a non-const getter for a member, rather than just making the member public?




                Several possible reasons reasons:



                1. Easy to instrument



                Who said the non-const getter needs to be just:



                    T& get() { return val; }


                ? it could well be something like:



                    T& get() { 
                if (check_for_something_bad()) {
                throw std::runtime_error{"Attempt to mutate val when bad things have happened");
                }
                return val;
                }

                However, as @BenVoigt suggests, it is more appropriate to wait until the caller actually tries to mutate the value through the reference before spewing an error.


                2. Cultural convention / "the boss said so"



                Some organizations enforce coding standards. These coding standards are sometimes authored by people who are possibly overly-defensive. So, you might see something like:




                Unless your class is a "plain old data" type, no data members may be public. You may use getter methods for such non-public members as necessary.




                and then, even if it makes sense for a specific class to just allow non-const access, it won't happen.



                3. Maybe val just isn't there?



                You've given an example in which val actually exists in an instance of the class. But actually - it doesn't have to! The get() method could return some sort of a proxy object, which, upon assignment, mutation etc. performs some computation (e.g. storing or retrieving data in a database).



                4. Allows changing class internals later without changing user code



                Now, reading items 1. or 3, above, you might ask "but my struct S does have val!" or "by my get() doesn't do anything interesting!" - well, true, they don't; but you might want to change this behavior in the future. Without a get(), all of your class' users will need to change their code. With a get(), you only need to make changes to the implementation of struct S.



                Now, I don't advocate for this kind of a design approach approach, but some programmers do.






                share|improve this answer



















                • 1




                  "Attempt to mutate val when bad things have happened" is just incorrect. Selection of const or non-const member function depends on the qualifications of the this object, and not how the return value is being used. In particular, a non-const getter cannot assume mutation is occurring.
                  – Ben Voigt
                  Dec 9 at 0:48










                • @BenVoigt: Suppose S is something NuclearMissilePosition, or PatientInfusionValueState. These are mutable, and should be mutable, but under certain conditions I might not want . Now, you could say "ok, only let friend functions mutate them then", or "write a setter function then", but this is also a way to do it.
                  – einpoklum
                  Dec 9 at 10:42










                • But when you cannot distinguish between get and set, your error message should reflect that uncertainty, not claim mutation was attempted.
                  – Ben Voigt
                  Dec 10 at 0:30










                • Ok, fair enough.
                  – einpoklum
                  Dec 11 at 15:46
















                8














                First let me rephrase your question:




                Why have a non-const getter for a member, rather than just making the member public?




                Several possible reasons reasons:



                1. Easy to instrument



                Who said the non-const getter needs to be just:



                    T& get() { return val; }


                ? it could well be something like:



                    T& get() { 
                if (check_for_something_bad()) {
                throw std::runtime_error{"Attempt to mutate val when bad things have happened");
                }
                return val;
                }

                However, as @BenVoigt suggests, it is more appropriate to wait until the caller actually tries to mutate the value through the reference before spewing an error.


                2. Cultural convention / "the boss said so"



                Some organizations enforce coding standards. These coding standards are sometimes authored by people who are possibly overly-defensive. So, you might see something like:




                Unless your class is a "plain old data" type, no data members may be public. You may use getter methods for such non-public members as necessary.




                and then, even if it makes sense for a specific class to just allow non-const access, it won't happen.



                3. Maybe val just isn't there?



                You've given an example in which val actually exists in an instance of the class. But actually - it doesn't have to! The get() method could return some sort of a proxy object, which, upon assignment, mutation etc. performs some computation (e.g. storing or retrieving data in a database).



                4. Allows changing class internals later without changing user code



                Now, reading items 1. or 3, above, you might ask "but my struct S does have val!" or "by my get() doesn't do anything interesting!" - well, true, they don't; but you might want to change this behavior in the future. Without a get(), all of your class' users will need to change their code. With a get(), you only need to make changes to the implementation of struct S.



                Now, I don't advocate for this kind of a design approach approach, but some programmers do.






                share|improve this answer



















                • 1




                  "Attempt to mutate val when bad things have happened" is just incorrect. Selection of const or non-const member function depends on the qualifications of the this object, and not how the return value is being used. In particular, a non-const getter cannot assume mutation is occurring.
                  – Ben Voigt
                  Dec 9 at 0:48










                • @BenVoigt: Suppose S is something NuclearMissilePosition, or PatientInfusionValueState. These are mutable, and should be mutable, but under certain conditions I might not want . Now, you could say "ok, only let friend functions mutate them then", or "write a setter function then", but this is also a way to do it.
                  – einpoklum
                  Dec 9 at 10:42










                • But when you cannot distinguish between get and set, your error message should reflect that uncertainty, not claim mutation was attempted.
                  – Ben Voigt
                  Dec 10 at 0:30










                • Ok, fair enough.
                  – einpoklum
                  Dec 11 at 15:46














                8












                8








                8






                First let me rephrase your question:




                Why have a non-const getter for a member, rather than just making the member public?




                Several possible reasons reasons:



                1. Easy to instrument



                Who said the non-const getter needs to be just:



                    T& get() { return val; }


                ? it could well be something like:



                    T& get() { 
                if (check_for_something_bad()) {
                throw std::runtime_error{"Attempt to mutate val when bad things have happened");
                }
                return val;
                }

                However, as @BenVoigt suggests, it is more appropriate to wait until the caller actually tries to mutate the value through the reference before spewing an error.


                2. Cultural convention / "the boss said so"



                Some organizations enforce coding standards. These coding standards are sometimes authored by people who are possibly overly-defensive. So, you might see something like:




                Unless your class is a "plain old data" type, no data members may be public. You may use getter methods for such non-public members as necessary.




                and then, even if it makes sense for a specific class to just allow non-const access, it won't happen.



                3. Maybe val just isn't there?



                You've given an example in which val actually exists in an instance of the class. But actually - it doesn't have to! The get() method could return some sort of a proxy object, which, upon assignment, mutation etc. performs some computation (e.g. storing or retrieving data in a database).



                4. Allows changing class internals later without changing user code



                Now, reading items 1. or 3, above, you might ask "but my struct S does have val!" or "by my get() doesn't do anything interesting!" - well, true, they don't; but you might want to change this behavior in the future. Without a get(), all of your class' users will need to change their code. With a get(), you only need to make changes to the implementation of struct S.



                Now, I don't advocate for this kind of a design approach approach, but some programmers do.






                share|improve this answer














                First let me rephrase your question:




                Why have a non-const getter for a member, rather than just making the member public?




                Several possible reasons reasons:



                1. Easy to instrument



                Who said the non-const getter needs to be just:



                    T& get() { return val; }


                ? it could well be something like:



                    T& get() { 
                if (check_for_something_bad()) {
                throw std::runtime_error{"Attempt to mutate val when bad things have happened");
                }
                return val;
                }

                However, as @BenVoigt suggests, it is more appropriate to wait until the caller actually tries to mutate the value through the reference before spewing an error.


                2. Cultural convention / "the boss said so"



                Some organizations enforce coding standards. These coding standards are sometimes authored by people who are possibly overly-defensive. So, you might see something like:




                Unless your class is a "plain old data" type, no data members may be public. You may use getter methods for such non-public members as necessary.




                and then, even if it makes sense for a specific class to just allow non-const access, it won't happen.



                3. Maybe val just isn't there?



                You've given an example in which val actually exists in an instance of the class. But actually - it doesn't have to! The get() method could return some sort of a proxy object, which, upon assignment, mutation etc. performs some computation (e.g. storing or retrieving data in a database).



                4. Allows changing class internals later without changing user code



                Now, reading items 1. or 3, above, you might ask "but my struct S does have val!" or "by my get() doesn't do anything interesting!" - well, true, they don't; but you might want to change this behavior in the future. Without a get(), all of your class' users will need to change their code. With a get(), you only need to make changes to the implementation of struct S.



                Now, I don't advocate for this kind of a design approach approach, but some programmers do.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Dec 11 at 15:45

























                answered Dec 8 at 14:33









                einpoklum

                33.3k26118234




                33.3k26118234








                • 1




                  "Attempt to mutate val when bad things have happened" is just incorrect. Selection of const or non-const member function depends on the qualifications of the this object, and not how the return value is being used. In particular, a non-const getter cannot assume mutation is occurring.
                  – Ben Voigt
                  Dec 9 at 0:48










                • @BenVoigt: Suppose S is something NuclearMissilePosition, or PatientInfusionValueState. These are mutable, and should be mutable, but under certain conditions I might not want . Now, you could say "ok, only let friend functions mutate them then", or "write a setter function then", but this is also a way to do it.
                  – einpoklum
                  Dec 9 at 10:42










                • But when you cannot distinguish between get and set, your error message should reflect that uncertainty, not claim mutation was attempted.
                  – Ben Voigt
                  Dec 10 at 0:30










                • Ok, fair enough.
                  – einpoklum
                  Dec 11 at 15:46














                • 1




                  "Attempt to mutate val when bad things have happened" is just incorrect. Selection of const or non-const member function depends on the qualifications of the this object, and not how the return value is being used. In particular, a non-const getter cannot assume mutation is occurring.
                  – Ben Voigt
                  Dec 9 at 0:48










                • @BenVoigt: Suppose S is something NuclearMissilePosition, or PatientInfusionValueState. These are mutable, and should be mutable, but under certain conditions I might not want . Now, you could say "ok, only let friend functions mutate them then", or "write a setter function then", but this is also a way to do it.
                  – einpoklum
                  Dec 9 at 10:42










                • But when you cannot distinguish between get and set, your error message should reflect that uncertainty, not claim mutation was attempted.
                  – Ben Voigt
                  Dec 10 at 0:30










                • Ok, fair enough.
                  – einpoklum
                  Dec 11 at 15:46








                1




                1




                "Attempt to mutate val when bad things have happened" is just incorrect. Selection of const or non-const member function depends on the qualifications of the this object, and not how the return value is being used. In particular, a non-const getter cannot assume mutation is occurring.
                – Ben Voigt
                Dec 9 at 0:48




                "Attempt to mutate val when bad things have happened" is just incorrect. Selection of const or non-const member function depends on the qualifications of the this object, and not how the return value is being used. In particular, a non-const getter cannot assume mutation is occurring.
                – Ben Voigt
                Dec 9 at 0:48












                @BenVoigt: Suppose S is something NuclearMissilePosition, or PatientInfusionValueState. These are mutable, and should be mutable, but under certain conditions I might not want . Now, you could say "ok, only let friend functions mutate them then", or "write a setter function then", but this is also a way to do it.
                – einpoklum
                Dec 9 at 10:42




                @BenVoigt: Suppose S is something NuclearMissilePosition, or PatientInfusionValueState. These are mutable, and should be mutable, but under certain conditions I might not want . Now, you could say "ok, only let friend functions mutate them then", or "write a setter function then", but this is also a way to do it.
                – einpoklum
                Dec 9 at 10:42












                But when you cannot distinguish between get and set, your error message should reflect that uncertainty, not claim mutation was attempted.
                – Ben Voigt
                Dec 10 at 0:30




                But when you cannot distinguish between get and set, your error message should reflect that uncertainty, not claim mutation was attempted.
                – Ben Voigt
                Dec 10 at 0:30












                Ok, fair enough.
                – einpoklum
                Dec 11 at 15:46




                Ok, fair enough.
                – einpoklum
                Dec 11 at 15:46











                5














                get() is callable by non const objects which are allowed to mutate, you can do:



                S r(0);
                r.get() = 1;


                but if you make r const as const S r(0), the line r.get() = 1 no longer compile, not even to retrieve the value, that's why you need a const version const T& get() const to at least to able to retrieve the value for const objects, doing so allows you do:



                const S r(0)
                int val = r.get()


                The const version of member functions try to be consistent with the constness property of the object the call is made on, i.e if the object is immutable by being const and the member function returns a reference, it may reflect the constness of the caller by returning a const reference, thus preserving the immutability property of the object.






                share|improve this answer



















                • 1




                  OP was asking, I'm sure, why have this method rather than just giving access to the member itself.
                  – einpoklum
                  Dec 8 at 14:13






                • 1




                  @einpoklum He was more interested in the reason and uses cases of having two different versions of get to perform the same action "return val" ... check at his last 2 paragraphs.
                  – Jans
                  Dec 8 at 14:17
















                5














                get() is callable by non const objects which are allowed to mutate, you can do:



                S r(0);
                r.get() = 1;


                but if you make r const as const S r(0), the line r.get() = 1 no longer compile, not even to retrieve the value, that's why you need a const version const T& get() const to at least to able to retrieve the value for const objects, doing so allows you do:



                const S r(0)
                int val = r.get()


                The const version of member functions try to be consistent with the constness property of the object the call is made on, i.e if the object is immutable by being const and the member function returns a reference, it may reflect the constness of the caller by returning a const reference, thus preserving the immutability property of the object.






                share|improve this answer



















                • 1




                  OP was asking, I'm sure, why have this method rather than just giving access to the member itself.
                  – einpoklum
                  Dec 8 at 14:13






                • 1




                  @einpoklum He was more interested in the reason and uses cases of having two different versions of get to perform the same action "return val" ... check at his last 2 paragraphs.
                  – Jans
                  Dec 8 at 14:17














                5












                5








                5






                get() is callable by non const objects which are allowed to mutate, you can do:



                S r(0);
                r.get() = 1;


                but if you make r const as const S r(0), the line r.get() = 1 no longer compile, not even to retrieve the value, that's why you need a const version const T& get() const to at least to able to retrieve the value for const objects, doing so allows you do:



                const S r(0)
                int val = r.get()


                The const version of member functions try to be consistent with the constness property of the object the call is made on, i.e if the object is immutable by being const and the member function returns a reference, it may reflect the constness of the caller by returning a const reference, thus preserving the immutability property of the object.






                share|improve this answer














                get() is callable by non const objects which are allowed to mutate, you can do:



                S r(0);
                r.get() = 1;


                but if you make r const as const S r(0), the line r.get() = 1 no longer compile, not even to retrieve the value, that's why you need a const version const T& get() const to at least to able to retrieve the value for const objects, doing so allows you do:



                const S r(0)
                int val = r.get()


                The const version of member functions try to be consistent with the constness property of the object the call is made on, i.e if the object is immutable by being const and the member function returns a reference, it may reflect the constness of the caller by returning a const reference, thus preserving the immutability property of the object.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Dec 8 at 17:51

























                answered Dec 8 at 13:41









                Jans

                7,63422334




                7,63422334








                • 1




                  OP was asking, I'm sure, why have this method rather than just giving access to the member itself.
                  – einpoklum
                  Dec 8 at 14:13






                • 1




                  @einpoklum He was more interested in the reason and uses cases of having two different versions of get to perform the same action "return val" ... check at his last 2 paragraphs.
                  – Jans
                  Dec 8 at 14:17














                • 1




                  OP was asking, I'm sure, why have this method rather than just giving access to the member itself.
                  – einpoklum
                  Dec 8 at 14:13






                • 1




                  @einpoklum He was more interested in the reason and uses cases of having two different versions of get to perform the same action "return val" ... check at his last 2 paragraphs.
                  – Jans
                  Dec 8 at 14:17








                1




                1




                OP was asking, I'm sure, why have this method rather than just giving access to the member itself.
                – einpoklum
                Dec 8 at 14:13




                OP was asking, I'm sure, why have this method rather than just giving access to the member itself.
                – einpoklum
                Dec 8 at 14:13




                1




                1




                @einpoklum He was more interested in the reason and uses cases of having two different versions of get to perform the same action "return val" ... check at his last 2 paragraphs.
                – Jans
                Dec 8 at 14:17




                @einpoklum He was more interested in the reason and uses cases of having two different versions of get to perform the same action "return val" ... check at his last 2 paragraphs.
                – Jans
                Dec 8 at 14:17











                3














                It depends on the purpose of S. If it's some kind of a thin wrapper, it might be appropriate to allow the user to access the underlaying value directly.



                One of the real-life examples is std::reference_wrapper.






                share|improve this answer





















                • This is likely the "spot on" answer. Useful when encapsulating C types for external libraries and such.
                  – pipe
                  Dec 8 at 17:16










                • In my opinion, reference_wrapper does a different thing. In OP's example, with get(), you can modify the value of the member. With reference_wrapper::get, you cannot modify which object it points to, you can only modify the pointed object.
                  – geza
                  Dec 8 at 20:20










                • @geza reference_wrapper exposes reference semantics, so its "value" is the wrapped object. The fact it's hold by pointer is just an implementation detail.
                  – Igor R.
                  Dec 8 at 21:29










                • That's why it is not relevant here. In OP's example, get() returns a reference to a member, which is contained within the object. reference_wrapper doesn't do this., its get() function does something else. "Is there any case where it makes sense to have non-const get function that returns val?". reference_wrapper returns the value pointed to, not the value itself.
                  – geza
                  Dec 8 at 21:36
















                3














                It depends on the purpose of S. If it's some kind of a thin wrapper, it might be appropriate to allow the user to access the underlaying value directly.



                One of the real-life examples is std::reference_wrapper.






                share|improve this answer





















                • This is likely the "spot on" answer. Useful when encapsulating C types for external libraries and such.
                  – pipe
                  Dec 8 at 17:16










                • In my opinion, reference_wrapper does a different thing. In OP's example, with get(), you can modify the value of the member. With reference_wrapper::get, you cannot modify which object it points to, you can only modify the pointed object.
                  – geza
                  Dec 8 at 20:20










                • @geza reference_wrapper exposes reference semantics, so its "value" is the wrapped object. The fact it's hold by pointer is just an implementation detail.
                  – Igor R.
                  Dec 8 at 21:29










                • That's why it is not relevant here. In OP's example, get() returns a reference to a member, which is contained within the object. reference_wrapper doesn't do this., its get() function does something else. "Is there any case where it makes sense to have non-const get function that returns val?". reference_wrapper returns the value pointed to, not the value itself.
                  – geza
                  Dec 8 at 21:36














                3












                3








                3






                It depends on the purpose of S. If it's some kind of a thin wrapper, it might be appropriate to allow the user to access the underlaying value directly.



                One of the real-life examples is std::reference_wrapper.






                share|improve this answer












                It depends on the purpose of S. If it's some kind of a thin wrapper, it might be appropriate to allow the user to access the underlaying value directly.



                One of the real-life examples is std::reference_wrapper.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Dec 8 at 13:48









                Igor R.

                10.6k12959




                10.6k12959












                • This is likely the "spot on" answer. Useful when encapsulating C types for external libraries and such.
                  – pipe
                  Dec 8 at 17:16










                • In my opinion, reference_wrapper does a different thing. In OP's example, with get(), you can modify the value of the member. With reference_wrapper::get, you cannot modify which object it points to, you can only modify the pointed object.
                  – geza
                  Dec 8 at 20:20










                • @geza reference_wrapper exposes reference semantics, so its "value" is the wrapped object. The fact it's hold by pointer is just an implementation detail.
                  – Igor R.
                  Dec 8 at 21:29










                • That's why it is not relevant here. In OP's example, get() returns a reference to a member, which is contained within the object. reference_wrapper doesn't do this., its get() function does something else. "Is there any case where it makes sense to have non-const get function that returns val?". reference_wrapper returns the value pointed to, not the value itself.
                  – geza
                  Dec 8 at 21:36


















                • This is likely the "spot on" answer. Useful when encapsulating C types for external libraries and such.
                  – pipe
                  Dec 8 at 17:16










                • In my opinion, reference_wrapper does a different thing. In OP's example, with get(), you can modify the value of the member. With reference_wrapper::get, you cannot modify which object it points to, you can only modify the pointed object.
                  – geza
                  Dec 8 at 20:20










                • @geza reference_wrapper exposes reference semantics, so its "value" is the wrapped object. The fact it's hold by pointer is just an implementation detail.
                  – Igor R.
                  Dec 8 at 21:29










                • That's why it is not relevant here. In OP's example, get() returns a reference to a member, which is contained within the object. reference_wrapper doesn't do this., its get() function does something else. "Is there any case where it makes sense to have non-const get function that returns val?". reference_wrapper returns the value pointed to, not the value itself.
                  – geza
                  Dec 8 at 21:36
















                This is likely the "spot on" answer. Useful when encapsulating C types for external libraries and such.
                – pipe
                Dec 8 at 17:16




                This is likely the "spot on" answer. Useful when encapsulating C types for external libraries and such.
                – pipe
                Dec 8 at 17:16












                In my opinion, reference_wrapper does a different thing. In OP's example, with get(), you can modify the value of the member. With reference_wrapper::get, you cannot modify which object it points to, you can only modify the pointed object.
                – geza
                Dec 8 at 20:20




                In my opinion, reference_wrapper does a different thing. In OP's example, with get(), you can modify the value of the member. With reference_wrapper::get, you cannot modify which object it points to, you can only modify the pointed object.
                – geza
                Dec 8 at 20:20












                @geza reference_wrapper exposes reference semantics, so its "value" is the wrapped object. The fact it's hold by pointer is just an implementation detail.
                – Igor R.
                Dec 8 at 21:29




                @geza reference_wrapper exposes reference semantics, so its "value" is the wrapped object. The fact it's hold by pointer is just an implementation detail.
                – Igor R.
                Dec 8 at 21:29












                That's why it is not relevant here. In OP's example, get() returns a reference to a member, which is contained within the object. reference_wrapper doesn't do this., its get() function does something else. "Is there any case where it makes sense to have non-const get function that returns val?". reference_wrapper returns the value pointed to, not the value itself.
                – geza
                Dec 8 at 21:36




                That's why it is not relevant here. In OP's example, get() returns a reference to a member, which is contained within the object. reference_wrapper doesn't do this., its get() function does something else. "Is there any case where it makes sense to have non-const get function that returns val?". reference_wrapper returns the value pointed to, not the value itself.
                – geza
                Dec 8 at 21:36











                1














                No. If a getter simply returns a non-const reference to a member, like this:



                private:
                Object m_member;

                public:
                Object &getMember() {
                return m_member;
                }


                Then m_member should be public instead, and the accessor is not needed. There is absolutely no point making this member private, and then create an accessor, which gives all access to it.



                If you call getMember(), you can store the resulting reference to a pointer/reference, and afterwards, you can do whatever you want with m_member, the enclosing class will know nothing about it. It's the same, as if m_member had been public.



                Note, that if getMember() does some additional task (for example, it doesn't just simply return m_member, but lazily constructs it), then getMember() could be useful:



                Object &getMember() {
                if (!m_member) m_member = new Object;
                return *m_member;
                }





                share|improve this answer


























                  1














                  No. If a getter simply returns a non-const reference to a member, like this:



                  private:
                  Object m_member;

                  public:
                  Object &getMember() {
                  return m_member;
                  }


                  Then m_member should be public instead, and the accessor is not needed. There is absolutely no point making this member private, and then create an accessor, which gives all access to it.



                  If you call getMember(), you can store the resulting reference to a pointer/reference, and afterwards, you can do whatever you want with m_member, the enclosing class will know nothing about it. It's the same, as if m_member had been public.



                  Note, that if getMember() does some additional task (for example, it doesn't just simply return m_member, but lazily constructs it), then getMember() could be useful:



                  Object &getMember() {
                  if (!m_member) m_member = new Object;
                  return *m_member;
                  }





                  share|improve this answer
























                    1












                    1








                    1






                    No. If a getter simply returns a non-const reference to a member, like this:



                    private:
                    Object m_member;

                    public:
                    Object &getMember() {
                    return m_member;
                    }


                    Then m_member should be public instead, and the accessor is not needed. There is absolutely no point making this member private, and then create an accessor, which gives all access to it.



                    If you call getMember(), you can store the resulting reference to a pointer/reference, and afterwards, you can do whatever you want with m_member, the enclosing class will know nothing about it. It's the same, as if m_member had been public.



                    Note, that if getMember() does some additional task (for example, it doesn't just simply return m_member, but lazily constructs it), then getMember() could be useful:



                    Object &getMember() {
                    if (!m_member) m_member = new Object;
                    return *m_member;
                    }





                    share|improve this answer












                    No. If a getter simply returns a non-const reference to a member, like this:



                    private:
                    Object m_member;

                    public:
                    Object &getMember() {
                    return m_member;
                    }


                    Then m_member should be public instead, and the accessor is not needed. There is absolutely no point making this member private, and then create an accessor, which gives all access to it.



                    If you call getMember(), you can store the resulting reference to a pointer/reference, and afterwards, you can do whatever you want with m_member, the enclosing class will know nothing about it. It's the same, as if m_member had been public.



                    Note, that if getMember() does some additional task (for example, it doesn't just simply return m_member, but lazily constructs it), then getMember() could be useful:



                    Object &getMember() {
                    if (!m_member) m_member = new Object;
                    return *m_member;
                    }






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Dec 8 at 14:17









                    geza

                    12.6k32775




                    12.6k32775























                        0














                        I would also like to point out the practical side of the question. For example, you want to aggregate your object Bar into another object Foo and create constant method doSomething which uses Bar only for reading:



                        class Foo
                        {
                        Bar bar_;
                        public:
                        void doSomething() const
                        {
                        //bar_.get();
                        }
                        }


                        You have a problem! You are absolutely sure that you do not change the Foo object, you want to mark this by const modificator, but you cannot do it, because get is not const. In other words, you create your own problems for the future and complicate the writing of clear and high-quality code. But you can implement two versions for get if you really need it:



                        class Bar
                        {
                        int data = 1;
                        public:
                        int& get() { return data; };
                        const int& get() const { return data; };
                        };


                        such a situation can arise if you ALREADY have a code in which constant modifiers are ignored, therefore such a situation is common:



                        foo(int* a); // Just get a, don`t modified
                        foo(&bar_.get()); // need non constant get()





                        share|improve this answer




























                          0














                          I would also like to point out the practical side of the question. For example, you want to aggregate your object Bar into another object Foo and create constant method doSomething which uses Bar only for reading:



                          class Foo
                          {
                          Bar bar_;
                          public:
                          void doSomething() const
                          {
                          //bar_.get();
                          }
                          }


                          You have a problem! You are absolutely sure that you do not change the Foo object, you want to mark this by const modificator, but you cannot do it, because get is not const. In other words, you create your own problems for the future and complicate the writing of clear and high-quality code. But you can implement two versions for get if you really need it:



                          class Bar
                          {
                          int data = 1;
                          public:
                          int& get() { return data; };
                          const int& get() const { return data; };
                          };


                          such a situation can arise if you ALREADY have a code in which constant modifiers are ignored, therefore such a situation is common:



                          foo(int* a); // Just get a, don`t modified
                          foo(&bar_.get()); // need non constant get()





                          share|improve this answer


























                            0












                            0








                            0






                            I would also like to point out the practical side of the question. For example, you want to aggregate your object Bar into another object Foo and create constant method doSomething which uses Bar only for reading:



                            class Foo
                            {
                            Bar bar_;
                            public:
                            void doSomething() const
                            {
                            //bar_.get();
                            }
                            }


                            You have a problem! You are absolutely sure that you do not change the Foo object, you want to mark this by const modificator, but you cannot do it, because get is not const. In other words, you create your own problems for the future and complicate the writing of clear and high-quality code. But you can implement two versions for get if you really need it:



                            class Bar
                            {
                            int data = 1;
                            public:
                            int& get() { return data; };
                            const int& get() const { return data; };
                            };


                            such a situation can arise if you ALREADY have a code in which constant modifiers are ignored, therefore such a situation is common:



                            foo(int* a); // Just get a, don`t modified
                            foo(&bar_.get()); // need non constant get()





                            share|improve this answer














                            I would also like to point out the practical side of the question. For example, you want to aggregate your object Bar into another object Foo and create constant method doSomething which uses Bar only for reading:



                            class Foo
                            {
                            Bar bar_;
                            public:
                            void doSomething() const
                            {
                            //bar_.get();
                            }
                            }


                            You have a problem! You are absolutely sure that you do not change the Foo object, you want to mark this by const modificator, but you cannot do it, because get is not const. In other words, you create your own problems for the future and complicate the writing of clear and high-quality code. But you can implement two versions for get if you really need it:



                            class Bar
                            {
                            int data = 1;
                            public:
                            int& get() { return data; };
                            const int& get() const { return data; };
                            };


                            such a situation can arise if you ALREADY have a code in which constant modifiers are ignored, therefore such a situation is common:



                            foo(int* a); // Just get a, don`t modified
                            foo(&bar_.get()); // need non constant get()






                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Dec 8 at 14:59

























                            answered Dec 8 at 14:46









                            Dmytro Dadyka

                            632117




                            632117






























                                draft saved

                                draft discarded




















































                                Thanks for contributing an answer to Stack Overflow!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.





                                Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                                Please pay close attention to the following guidance:


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53683047%2freasons-for-defining-non-const-get-member-functions%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                Popular posts from this blog

                                "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

                                Alcedinidae

                                Origin of the phrase “under your belt”?