0

In attempting to brush up on my C++, I've been trying to find out the best-practice way of creating accessors.

I want to clarify my understanding and find out if what I'm doing is right. I have several questions, but they seem pretty simple so I've rolled them all into this one Stack Overflow question.

The following is some example code representing what I 'think' is the correct way of doing things:

class MyClass
{
private:
    std::string StringMember_;
    int IntMember_;

public:
    MyClass(const std::string &stringInput, const int &intInput) : StringMember_(stringInput), IntMember_(intInput)
    {
    }

    const std::string &StringMember() const
    {
        return StringMember_;
    }

    void StringMember(const std::string &stringInput)
    {
        StringMember_ = stringInput;
    }

    const int &IntMember() const
    {
        return IntMember_;
    }

    void IntMember(const int &intInput)
    {
        IntMember_ = intInput;
    }
};

My questions are:

Where my accessors return a const reference variable, ie const std::string, this means that it (my class's member variable) cannot be changed. Is that correct?

The last const before a method's body indicates that no members of the class for which that method is a part of can be altered, unless they are designated mutable. Is this also correct?

Where I'm passing in const method parameters, this means that I ensure these parameters are always stored as they were passed in, thus protecting any original variables being passed in from being altered by the method body. Is this also correct?

With regards to the mutable keyword, under what circumstances would I actually want to use this? I've been struggling to think of a good scenario where I'd have a const method that needed to modify class members.

Accessors seem like a good idea, even for data that will never be publicly exposed, because it ensures a single-point of entry, allowing for easier debugging and so on. Am I thinking along the right lines here, or is this in fact totally meaningless, and that there is no need for private accessors?

From a purely syntactical perspective, should I be writing my references like const int& intInput or const int &intInput. Does it really matter where the ampersand is, or is it just a matter of personal preference?

Finally, is what I'm doing in the example above good practice? I plan to start working on a larger personal project, and I want to have these core basics down before I start running into problems later.

I was using this as a reference: https://isocpp.org/wiki/faq/const-correctness

Interminable
  • 1,338
  • 3
  • 21
  • 52
  • Why the downvote? Also, I've updated the title to try and make it a bit clearer. – Interminable May 23 '16 at 14:16
  • My guess is that it's because you asked more than one question. We prefer you to ask one question per question. That said, all questions except the last one are trivial, so it's OK in my opinion. The last question however, is both too broad and opinion based for stackoverflow. – eerorika May 23 '16 at 14:25
  • I did think they were too trivial for individual questions. As for the last one, I was mainly trying to find out whether or not I was doing anything terribly wrong that I hadn't identified. – Interminable May 23 '16 at 14:30

3 Answers3

4

Where my accessors return a const reference variable, ie const std::string, this means that it (my class's member variable) cannot be changed. Is that correct?

Correct. A variable cannot be changed through a const reference.

The last const before a method's body indicates that no members of the class for which that method is a part of can be altered, unless they are designated mutable. Is this also correct?

Correct. It also allows the function to be called on a const object.

Where I'm passing in const method parameters, this means that I ensure these parameters are always stored as they were passed in, thus protecting any original variables being passed in from being altered by the method body. Is this also correct?

Correct. Same can be achieved with accepting the argument by value.

With regards to the mutable keyword, under what circumstances would I actually want to use this?

See When have you used C++ 'mutable' keyword?

Accessors seem like a good idea, even for data that will never be publicly exposed, because it ensures a single-point of entry, allowing for easier debugging and so on. Am I thinking along the right lines here

I don't buy this argument. Watchpoints allow for easy debugging of member variables regardless of where they're accessed from.

From a purely syntactical perspective, should I be writing my references like const int& intInput or const int &intInput.

Both are syntactically equivalent and the choice between them is purely aesthetic.

Finally, is what I'm doing in the example above good practice?

There is no general answer. Accessors are sometimes useful. Often they're redundant. If you provide a function that allows setting the value directly, such as you do here, then you might as well get rid of the accessors and make the member public.

Community
  • 1
  • 1
eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Marked as the answer as you've had a good crack at tackling everything I asked! I'm still not completely sold on the anti-accessor idea though (the debugging point was just an example). I never used to use them at all, but having a way to control the access point for member data seems good to me because in the event you needed to, say, add a check for setting a value for member data, does not having an accessor make sense? – Interminable May 23 '16 at 14:35
  • 1
    @Interminable well, I can't counter arguments that you didn't already give :) with a private interface if your design changes and you later want to prevent direct assignment in favour of a checked approach, it is probably not a problem to change the visibility, add an accessor, and modify the code to use it. In the case of a public API, your argument is valid. – eerorika May 23 '16 at 15:11
0

Seems to me like you have a pretty good handle on the concepts here. As far as a mutable example there are lots, here's one: you have a search method, and for performance reasons you cache the last search results... that internal cache would need to be mutable for a const search method. I.e. the external behavior didn't change, but internally something might change.

mark
  • 5,269
  • 2
  • 21
  • 34
0

Here is some examples for mutable:

memoiziation caches, for when something is referencially-transparent, but expensive to calculate, the first call to the (const-qualified) accessor calculates the value and stores it in a mutable member hash table, second and subsequent calls fetch the value from the table instead.

access counters, timing, loggers, and other instrumentation that needs to change some state when a const-qualified accessor is called

From https://www.quora.com/When-should-I-actually-use-a-mutable-keyword-in-C++

Community
  • 1
  • 1
Shangtong Zhang
  • 1,579
  • 1
  • 11
  • 18