14

I've recently spent a lot of time with javascript and am now coming back to C++. When I'm accessing a class member from a method I feed inclined to prefix it with this->.

class Foo {

  int _bar;

public:  
  /* ... */

  void setBar(int bar) {
    this->_bar = bar;
    // as opposed to
    _bar = bar;
  }
}

On reading, it saves me a brain cycle when trying to figure out where it's coming from.
Are there any reasons I shouldn't do this?

Ilia Choly
  • 18,070
  • 14
  • 92
  • 160
  • That extra brain cycle is saved by reading the function name. – chris Nov 13 '12 at 20:06
  • 11
    Yes -- because to others who are actually accustomed to C++, it will take even more extra brain cycles, trying to figure out whether you think you're writing something where `this->` is actually needed, or you're just ignorant. – Jerry Coffin Nov 13 '12 at 20:07
  • @chris There are other circumstances where the method might be more complicated than a getter/setter. – Ryan Amos Nov 13 '12 at 20:07
  • @RyanAmos, True, but the function name should always suffice to mostly know what it's doing. – chris Nov 13 '12 at 20:08
  • @chris Maybe so for the result, but not the clever implementation. – Ryan Amos Nov 13 '12 at 20:09
  • @RyanAmos, Anything seen as clever should probably have a comment :) – chris Nov 13 '12 at 20:10
  • @RyanAmos: For the clever implementation you need comments, not `this->` – David Rodríguez - dribeas Nov 13 '12 at 20:12
  • @DavidRodríguez-dribeas And `this->` somehow excludes comments? Adding `this->` can only make things more clear. If you don't like `this->`, find&replace "this->" with "". – Ryan Amos Nov 13 '12 at 20:19
  • @RyanAmos: No, you can have both comments to explain the code and `this->`, but the complexity of the code is not a reason to add `this->` as your previous comment seemed to imply. – David Rodríguez - dribeas Nov 13 '12 at 20:21
  • @RyanAmos: OP suggests `this->` all the time as a means of documentation. Using `this->` is not needed in any but a few unusual circumstances. In those unusual circumstances, documentation in the form of comments could be considered as required. Using `this->` in addition to the comments would not hurt, but `this->` is not a replacement for comments. `this->` is generally only needed when name hiding is taking place, which is something I would classify as a **defect**, not cleverness. Using `this->` in those cases doesn't explain why the names were hidden. "Why" is why we need comments – John Dibling Nov 13 '12 at 21:08
  • 7
    Using `this->` to denote member variable access is merely a matter of style. You should be consistent in your style in a given project. Using a non-needed `this->` as a convention in a project does not generate a *defect*, it just is a different convention. And yes, people get very religious about such conventions. – Yakk - Adam Nevraumont Nov 13 '12 at 21:37
  • See also: [Why use prefixes on member variables in C++ classes](http://stackoverflow.com/questions/1228161). – Pang Nov 14 '12 at 02:16

8 Answers8

13

Using this-> for class variables is perfectly acceptable.

However, don't start identifiers with an underscore, or include any identifiers with double underscore __ anywhere. There are some classes of reserved symbols that are easy to hit if you violate either of these two rules of thumb. (In particular, _IdentifierStartingWithACapital is reserved by the standard for compilers).

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • 1
    Identifiers starting with an underscore and a lower case letter are not reserved though, so this is not an issue. –  Nov 13 '12 at 20:09
  • @delnan: people forgetting the rules _is_ an issue. So as Yakk explains, some classes of reserved symbols are easy to hit if you violate the rule of thumb: don't start identifiers with an underscore. – Mooing Duck Nov 13 '12 at 20:10
  • See http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier – Dan Nov 13 '12 at 20:10
  • @delnan, One small fix on that: They are in the global scope. We're talking about class scope here, but one could extrapolate that. – chris Nov 13 '12 at 20:11
  • To some people (including me), "class variable" is a static member. – BatchyX Nov 13 '12 at 20:12
  • 3
    IMO, "perfectly acceptable" is overstating things. The *compiler* won't complain, but you should write your code to be readable by other programmers, not just the compiler. From that viewpoint, it's clearly a bad practice and should definitely be avoided. – Jerry Coffin Nov 13 '12 at 20:25
  • 4
    The acceptance of this answer is an example of what Paul Simon once sang, "A man hears what he wants to hear and disregards the rest." – John Dibling Nov 13 '12 at 21:11
  • @Yakk: -1: I'd consider myself to be a competent programmer, and yet it would slow me down because I would be thinking "why would he have needed `this->` here? Is there a name hidden?" And then I'd have to examine the code carefully. – John Dibling Nov 13 '12 at 21:12
  • @JohnDibling because it disagrees with your style: if `this->` is used consistently in a project for member variables, you wouldn't keep thinking that, would you? It isn't a style I love, but it is only a style issue. – Yakk - Adam Nevraumont Nov 13 '12 at 21:22
  • @Yakk: I disagree. There *is* something wrong with using `this->` as documentation. It documents the wrong thing. See my answer. – John Dibling Nov 13 '12 at 21:31
  • 2
    @John You would be confused if an entire project used `this->` for all member variable access, and think they where documenting hidden member variable access each time? – Yakk - Adam Nevraumont Nov 13 '12 at 21:40
  • @Yakk: I'd be confused why the powers that be selected such an illogical naming scheme, yes. It would also be confusing when there actually *were* hidden names. Imagine how hard it would be to find *that* bug, in a codebase where `this->` was SOP. – John Dibling Nov 13 '12 at 21:44
  • 1
    How would it be harder than in a codebase where `this->` was not SOP? Compilers with decent warnings would still yell at you when you accessed a hiding variable. Ifyou are saying that you should avoid hiding member variables, that is good advice. But that is orthogonal to what the OP asked. – Yakk - Adam Nevraumont Nov 13 '12 at 22:08
10

In principle, accessing members via this-> is a coding style that can help in making things clearer, but it seems to be a matter of taste.

However, you also seem to use prefixing members with _ (underscore). I would say that is too much, you should go for either of the two styles.

Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
Zane
  • 926
  • 8
  • 21
  • 4
    You should not prefix anything with an underscore. – Dan Nov 13 '12 at 20:09
  • 2
    I usually suffix my members with underscores. Prefixing can lead to use of a reserved name. – chris Nov 13 '12 at 20:09
  • 4
    @dan: It is perfectly fine to prefix members with a single underscore (if they don't start with a capital letter). These type of comments are called 'Cult Programming', indicate a misunderstanding of the rule and spread a misconception – David Rodríguez - dribeas Nov 13 '12 at 20:15
  • @DavidRodríguez-dribeas, The *as long as it doesn't start with a capital letter* part is why I suffix them. It doesn't interfere with any name other than that which already ends with an underscore, but that's absurd name usage if you ask me. People coming from places such as C# might feel inclined to mix styles of capital letter public members (properties) and underscore prefixing. – chris Nov 13 '12 at 20:18
  • I'm aware of reserved names. But I like prefixing all private members with `_`. So if I type `this->_` auto-complete shows me all the private members in the current class. – Ilia Choly Nov 13 '12 at 20:20
  • @chris: If your coding guidelines determine that you don't start with capital letters it is fine. An advantage of prefixing rather than suffixing is that tools that with a single character you can filter in the set of candidates for completion if your tool offers autocompletion, allowing a fast way of *finding* what members are there. At any rate, in our coding guidelines the prefix is a regular character followed by the underscore. – David Rodríguez - dribeas Nov 13 '12 at 20:23
  • @DavidRodríguez-dribeas, I agree it offers benefits without problems with guidelines in place. It's something that the level of benefits varies per person. `m_` is a perfectly valid prefix to introduce the benefits of autocompletion with if you want that without the possibility of using a reserved name. I could just never get used to typing `m_` before everything. Of course if I end up somewhere that requires me to change that habit, it's a different story :) – chris Nov 13 '12 at 20:29
  • Thanks guys. While I normally don't use neither underscore suffixes nor prefixes, I learned something new about them. – Zane Nov 13 '12 at 21:18
7

Are there any reasons I shouldn't do this?

Yes, there is a reason why you shouldn't do this.

Referencing a member variable with this-> is strictly required only when a name has been hidden, such as with:

class Foo
{
public:
    void bang(int val);
    int val;
};

void Foo::bang(int val)
{
    val = val;
}

int main()
{
    Foo foo;
    foo.val = 42;
    foo.bang(84);
    cout << foo.val;

}

The output of this program is 42, not 84, because in bang the member variable has been hidden, and val = val results in a no-op. In this case, this-> is required:

void Foo::bang(int val)
{
    this->val = val;
}

In other cases, using this-> has no effect, so it is not needed.

That, in itself, is not a reason not to use this->. The maintennance of such a program is however a reason not to use this->.

You are using this-> as a means of documentation to specify that the vairable that follows is a member variable. However, to most programmers, that's not what usign this-> actually documents. What using this-> documents is:

There is a name that's been hidden here, so I'm using a special technique to work around that.

Since that's not what you wanted to convey, your documentation is broken.

Instead of using this-> to document that a name is a member variable, use a rational naming scheme consistently where member variables and method parameters can never be the same.

Edit Consider another illustration of the same idea.

Suppose in my codebase, you found this:

int main()
{
    int(*fn)(int) = pingpong;
    (fn)(42);
}

Quite an unusual construct, but being a skilled C++ programmer, you see what's happening here. fn is a pointer-to-function, and being assigned the value of pingpong, whatever that is. And then the function pointed to by pingpong is being called with the singe int value 42. So, wondering why in the world you need such a gizmo, you go looking for pingpong and find this:

static int(*pingpong)(int) = bangbang;

Ok, so what's bangbang?

int bangbang(int val)
{
    cout << val;
    return val+1;
}

"Now, wait a sec. What in the world is going on here? Why do we need to create a pointer-to-function and then call through that? Why not just call the function? Isn't this the same?"

int main()
{
    bangbang(42);
}

Yes, it is the same. The observable effects are the same.

Wondering if that's really all there is too it, you see:

/*  IMPLEMENTATION NOTE
 *
 *  I use pointers-to-function to call free functions
 *  to document the difference between free functions
 *  and member functions.
 */

So the only reason we're using the pointer-to-function is to show that the function being called is a free function and not a member function.

Does that seem like just a "matter of style" to you? Because it seems like insanity to me.

John Dibling
  • 99,718
  • 31
  • 186
  • 324
4

Here you will find:

Unless a class member name is hidden, using the class member name is equivalent to using the class member name with the this pointer and the class member access operator (->).

richbria90
  • 159
  • 2
  • 5
4

I think you do this backwards. You want the code to assure you that what happens is exactly what is expected.

Why add extra code to point out that nothing special is happening? Accessing class members in the member functions happen all the time. That's what would be expected. It would be much better to add extra info when it is not the normal things that happen.

In code like this

class Foo
{
 public:
    void setBar(int NewBar) 
    { Bar = NewBar; }

you ask yourself - "Where could the Bar come from?".

As this is a setter in a class, what would it set if not a class member variable?! If it wasn't, then there would be a reason to add a lot of info about what's actually going on here!

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
3

Since you are already using a convention to signify that an identifer is a data member (although not one I would recommend), adding this-> is simply redundant in almost all cases.

Dabbler
  • 9,733
  • 5
  • 41
  • 64
3

This is a somewhat subjective question obvously. this-> seems much more python-idiomatic than C++-idiomatic. There are only a handful of cases in C++ where the leading this-> is required, dealing with names in parent template classes. In general if your code is well organized it will be obvious to the reader that it's a member or local variable (globals should just be avoided), and reducing the amount to be read may reduce complexity. Additionally you can use an optional style (I like trailing _) to indicate member variables.

Mark B
  • 95,107
  • 10
  • 109
  • 188
2

It doesn't actually harm anything, but programmers experienced with OO will see it and find it odd. It's similarly surprising to see "yoda conditionals," ie if (0 == x).

Dan
  • 12,409
  • 3
  • 50
  • 87