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











up vote
16
down vote

favorite
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


















  • 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










  • 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
    2 days ago

















up vote
16
down vote

favorite
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


















  • 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










  • 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
    2 days ago















up vote
16
down vote

favorite
1









up vote
16
down vote

favorite
1






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

14311




14311








  • 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










  • 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
    2 days ago
















  • 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










  • 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
    2 days ago










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












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
2 days ago






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
2 days ago














6 Answers
6






active

oldest

votes

















up vote
12
down vote



accepted










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.



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






























    up vote
    6
    down vote













    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
      2 days ago










    • But when you cannot distinguish between get and set, your error message should reflect that uncertainty, not claim mutation was attempted.
      – Ben Voigt
      2 days ago










    • Ok, fair enough.
      – einpoklum
      15 hours ago


















    up vote
    4
    down vote













    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


















    up vote
    3
    down vote













    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


















    up vote
    1
    down vote













    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




























      up vote
      0
      down vote













      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










      New contributor




      Dmytro Dadyka is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.


















        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',
        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








        up vote
        12
        down vote



        accepted










        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.



        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



























          up vote
          12
          down vote



          accepted










          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.



          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

























            up vote
            12
            down vote



            accepted







            up vote
            12
            down vote



            accepted






            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.



            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.



            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 8 at 14:08

























            answered Dec 8 at 13:43









            user463035818

            16.1k42563




            16.1k42563
























                up vote
                6
                down vote













                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
                  2 days ago










                • But when you cannot distinguish between get and set, your error message should reflect that uncertainty, not claim mutation was attempted.
                  – Ben Voigt
                  2 days ago










                • Ok, fair enough.
                  – einpoklum
                  15 hours ago















                up vote
                6
                down vote













                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
                  2 days ago










                • But when you cannot distinguish between get and set, your error message should reflect that uncertainty, not claim mutation was attempted.
                  – Ben Voigt
                  2 days ago










                • Ok, fair enough.
                  – einpoklum
                  15 hours ago













                up vote
                6
                down vote










                up vote
                6
                down vote









                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 15 hours ago

























                answered Dec 8 at 14:33









                einpoklum

                33.1k26115234




                33.1k26115234








                • 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
                  2 days ago










                • But when you cannot distinguish between get and set, your error message should reflect that uncertainty, not claim mutation was attempted.
                  – Ben Voigt
                  2 days ago










                • Ok, fair enough.
                  – einpoklum
                  15 hours ago














                • 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
                  2 days ago










                • But when you cannot distinguish between get and set, your error message should reflect that uncertainty, not claim mutation was attempted.
                  – Ben Voigt
                  2 days ago










                • Ok, fair enough.
                  – einpoklum
                  15 hours ago








                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
                2 days ago




                @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
                2 days ago












                But when you cannot distinguish between get and set, your error message should reflect that uncertainty, not claim mutation was attempted.
                – Ben Voigt
                2 days ago




                But when you cannot distinguish between get and set, your error message should reflect that uncertainty, not claim mutation was attempted.
                – Ben Voigt
                2 days ago












                Ok, fair enough.
                – einpoklum
                15 hours ago




                Ok, fair enough.
                – einpoklum
                15 hours ago










                up vote
                4
                down vote













                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















                up vote
                4
                down vote













                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













                up vote
                4
                down vote










                up vote
                4
                down vote









                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,01922233




                7,01922233








                • 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










                up vote
                3
                down vote













                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















                up vote
                3
                down vote













                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













                up vote
                3
                down vote










                up vote
                3
                down vote









                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.5k12959




                10.5k12959












                • 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










                up vote
                1
                down vote













                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

























                  up vote
                  1
                  down vote













                  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























                    up vote
                    1
                    down vote










                    up vote
                    1
                    down vote









                    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.3k32775




                    12.3k32775






















                        up vote
                        0
                        down vote













                        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










                        New contributor




                        Dmytro Dadyka is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                        Check out our Code of Conduct.






















                          up vote
                          0
                          down vote













                          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










                          New contributor




                          Dmytro Dadyka is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                          Check out our Code of Conduct.




















                            up vote
                            0
                            down vote










                            up vote
                            0
                            down vote









                            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










                            New contributor




                            Dmytro Dadyka is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                            Check out our Code of Conduct.









                            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










                            New contributor




                            Dmytro Dadyka is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                            Check out our Code of Conduct.









                            share|improve this answer



                            share|improve this answer








                            edited Dec 8 at 14:59





















                            New contributor




                            Dmytro Dadyka is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                            Check out our Code of Conduct.









                            answered Dec 8 at 14:46









                            Dmytro Dadyka

                            24812




                            24812




                            New contributor




                            Dmytro Dadyka is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                            Check out our Code of Conduct.





                            New contributor





                            Dmytro Dadyka is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                            Check out our Code of Conduct.






                            Dmytro Dadyka is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                            Check out our Code of Conduct.






























                                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

                                If I really need a card on my start hand, how many mulligans make sense? [duplicate]

                                Alcedinidae

                                Can an atomic nucleus contain both particles and antiparticles? [duplicate]