24

I'm dealing with a large code base that uses the following construct throughout

class MyClass
{
public:
  void f(int x);
private:
  int x;
};


void MyClass::f(int x)
{
'
'
  this->x = x;
'
'
}

Personally, I'd always used and hence prefer the form

class MyClass
{
public:
  void f(int x);
private:
  int _x;
};


void MyClass::f(int x)
{
'
'
  _x = x;
'
'
}

The reasons I prefer the latter are that it is more succinct (less code = fewer potential bugs), and that I don't like having multiple variables of the same name in scope at the same time where I can avoid it. That said, I am seeing the former usage more and more often these days. Is there any upside to second approach that I am unaware of? (e.g. effect on compile time, use with templated code, etc...) Are the advantages of either approach significant enough merit a refactor to the other? Reason I ask, that while I don't like the second approach present in the code, the amount of effort and associated risk of introducing further bugs don't quite merit a refactor.

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
SmacL
  • 22,555
  • 12
  • 95
  • 149
  • 5
    You question has nothing to do with refactoring or codesmells. This is only related to the naming convention which you choose to follow - which in turn force you to use the `this` keyword in order to avoid ambiguity (and would not be needed if the parameter was named `y`). – vgru Jun 29 '09 at 09:50
  • @Groo, IMO, choosing a naming convention that is likely to lead to variable name ambiguity and hence bugs is a smell, as is being forced to use 'this' to resolve the ambiguity. If it's a smell, and it's code I'm likely to be working on, it is likely to lead to a refactor. – SmacL Jun 29 '09 at 10:29
  • I prefer using _x and the x the other way around, i.e. the _x is the temporary, just because it's one less keystroke. – Chris Huang-Leaver Jun 29 '09 at 10:46
  • But there is a *single* case which unambiguously differentiates between parameters, instance fields and static fields, regardless of your convention and style - which is the usage of `this` keyword (Google for "StyleCop SA1309"). Any other way is simply a preferred programmer's style and can change from one source to another. Don't get me wrong - I always prefix private fields with underscores. :) – vgru Jun 29 '09 at 11:07
  • Do not confuse more typing strokes and more code... both have the same amount of code, hence the same chance of bugs. The difference is that one has more keystrokes ans the other. Although this invalidates half your argument the ambiguity part remains for the this convention if this is omitted. – Newtopian Jul 15 '09 at 02:08
  • @Newtopian this->x = x is an explicit pointer dereference which is more code than _x =x, even if the latter includes a similar dereference implicitly and ends up in the same result once compiled. For example, say I accidentally typed thos->x instead of this->x where thos was a NULL pointer of type MyClass. Unlikely sure, but still scope for more bugs. – SmacL Jul 16 '09 at 07:26
  • For class members, I always use it like `m_varName`. So if you have a variable that is `varName` in the parameter, you can use it like `m_varName = varName;`. This makes it readable, you see which of the the variables are members, helps _immensely_ with the auto-complete when writing code and this is not a reserved name. – JohnJohn Jan 31 '15 at 13:46

15 Answers15

27

Your version is a bit cleaner, but while you're at it, I would:

  1. Avoid leading underscore: _x is ok until somebody chooses _MyField which is a reserved name. An initial underscore followed by a capital letter is not allowed as a variable name. See: What are the rules about using an underscore in a C++ identifier?
  2. Make the attribute private or protected: the change is safe if it compiles, and you'll ensure your setter will be used.
  3. The this-> story has a use, for example in templated code to make the field name dependent on your type (can solve some lookup issues).

A small example of name resolutions which are fixed by using an explicit this-> (tested with g++ 3.4.3):

#include <iostream>
#include <ostream>

class A
{
public:
  int g_;
  A() : g_(1) {}
  const char* f() { return __FUNCTION__; }
};

const char* f() { return __FUNCTION__; }
int g_ = -1;

template < typename Base >
struct Derived : public Base
{
  void print_conflicts()
  {
    std::cout << f() << std::endl; // Calls ::f()
    std::cout << this->f() << std::endl; // Calls A::f()
    std::cout << g_ << std::endl; // Prints global g_
    std::cout << this->g_ << std::endl; // Prints A::g_
  }
};

int main(int argc, char* argv[])
{
   Derived< A >().print_conflicts();
   return EXIT_SUCCESS;
}
Community
  • 1
  • 1
bltxd
  • 8,825
  • 5
  • 30
  • 44
  • Actually, the bulk of the code is actually MFC and ends up being m_ as per most MFC. I went with the simple underscore instead to make the question a bit more neutral, and similarly left out the private as it is a different issue. +1 for the point about templates, maybe you could supply a short example as it would really benefit the answer. – SmacL Jun 29 '09 at 10:09
  • 2
    Leading underscore is fine as long as the next character is lower case. – GManNickG Jun 29 '09 at 10:25
  • 4
    Correct, but the maintainer following you may not be aware of that. – bltxd Jun 29 '09 at 10:36
10

Field naming has nothing to do with a codesmell. As Neil said, field visibility is the only codesmell here.

There are various articles regarding naming conventions in C++:

etc.

Community
  • 1
  • 1
vgru
  • 49,838
  • 16
  • 120
  • 201
  • I wasn't actually asking whether the naming convention was a code smell, I was asking whether excessive use of 'this->' was a code smell. I suspect Marco (below) is right in that the practice of adding the 'this->' comes from a desire to use Intellisense/Code completion in some IDEs. If this is the case than I believe it probably is a code smell. – SmacL Jun 29 '09 at 13:13
4

This usage of 'this' is encouraged by Microsoft C# coding standards. It gives a good code clarity, and is intended to be a standard over the usage of m_ or _ or anything else in member variables.

Honestly, I really dislike underscore in names anyway, I used to prefix all my members by a single 'm'.

Jem
  • 2,255
  • 18
  • 25
  • 4
    Thanks for sharing your variable naming preference with us all. – Eric Jun 29 '09 at 09:50
  • 1
    C# coding standards :) To answer the question more explicitly, I would not consider it as a code smell, because it is even considered as good practice in another language where IMHO similar pros and cons apply. – Jem Jun 29 '09 at 09:54
  • 1
    @Eric it was to illustrate that it is a matter of taste. Underscores anywhere in non-standard library code tend to reduce the visibility, and could be considered as code smell, compared to the usage of this. This is of course just an opinion. – Jem Jun 29 '09 at 09:58
  • 2
    C# and C++ are different languages. In C++ this-> has a very specific use to force the lookup of an identifier in a template instantiation context as a member, rather than in the template definition context. A C++ coding standard might reasonably restrict the use of this-> to places where it is truly needed. This doesn't apply in C#. – CB Bailey Jun 29 '09 at 10:05
  • I tend to use m_ on MFC code and a single underscore elsewhere, again just personal preference. – SmacL Jun 29 '09 at 10:11
  • I've never seen the C# coding standard encourage `this`, though it did at one point discourage `m_` but they later backtracked and now give no recommendation on private fields. The .NET reference source uses `m_` prefixes a lot; FWIW in C# I use both `this` and a prefix for fields. IMO `this` alone isn't good enough because the compiler won't error out if you forget it, and you can very easily cause a `StackOverflowException` if you attempt to set a backing field in a property's setter. – jrh Apr 26 '19 at 17:25
3

A lot of people use this because in their IDE it will make a list of identifiers of the current class pop up.

I know I do in BCB.

I think the example you provide with the naming conflict is an exception. In Delphi though, style guidelines use a prefix (usually "a") for parameters to avoid exactly this.

Marco van de Voort
  • 25,628
  • 5
  • 56
  • 89
  • 1
    It's usually quicker to type Ctrl+Space or whatever the autocomplete shortcut for your IDE is; Visual Studio normally doesn't require this -> to see the methods and variables in scope. – Pete Kirkham Jun 29 '09 at 09:52
  • +1 for the most probable reason as to why I am seeing this so much in the code base. Interesting that the IDE is encouraging people to write code differently to how they would do it in a simpler editor. – SmacL Jun 29 '09 at 10:18
  • @Pete, agreed but I think Marco has probably given the reason why it is happening so much. – SmacL Jun 29 '09 at 10:19
  • Pete: BCB/Delphi do too, but this gives _only_ the identifiers in the class, not all in scope. – Marco van de Voort Jun 29 '09 at 10:37
3

My personal feeling is that fighting an existing coding convention is something you should not do. As Sutter/Alexandrescu puts it in their book 'C++ coding conventions': don't sweat the small stuff. Anyone is able to read the one or the other, whether there is a leading 'this->' or '_' or whatever.

However, consistency in naming conventions is something you typically do want, so sticking to one convention at some scope (at least file scope, ideally the entire code base, of course) is considered good practice. You mentioned that this style is used throughout a larger code base, so I think retrofitting another convention would be rather a bad idea.

If you, after all, find there is a good reason for changing it, don't do it manually. In the best case, your IDE supports these kind of 'refactorings'. Otherwise, write a script for changing it. Search & replace should be the last option. In any case, you should have a backup (source control) and some kind of automated test facility. Otherwise you won't have fun with it.

2

Using 'this' in this manner is IMO not a code smell, but is simply a personal preference. It is therefore not as important as consistency with the rest of the code in the system. If this code is inconsistent you could change it to match the other code. If by changing it you will introduce inconsistency with the majority of the rest of the code, that is very bad and I would leave it alone.

You don't want to ever get into a position of playing code tennis where somebody changes something purely to make it look "nice" only for somebody else to come along later with different tastes who then changes it back.

markh44
  • 5,804
  • 5
  • 28
  • 33
1

I always use the m_ naming convention. Although I dislike "Hungarian notation" in general, I find it very useful to see very clearly if I'm working with class member data. Also, I found using 2 identical variable names in the same scope too error prone.

Dimitri C.
  • 21,861
  • 21
  • 85
  • 101
0

I agree. I don't like that naming convention - I prefer one where there is an obvious distinction between member variables and local variables. What happens if you leave off the this?

1800 INFORMATION
  • 131,367
  • 29
  • 160
  • 239
0

class MyClass{
public:  
  int x;  
  void f(int xval);
};
//
void MyClass::f(int xval){  
  x = xval;
}
Alexey Malistov
  • 26,407
  • 13
  • 68
  • 88
  • He hasn't named the function paramter the same as the member variable -- therefore not overloading the name and forcing this-> – Pod Jun 29 '09 at 09:52
  • 4
    I do not think it brings any useful arguments to the discussion – Newtopian Jul 15 '09 at 02:11
0

In my opinion this tends to add clutter to the code, so I tend to use different variable names (depending on the convention, it might be an underscore, m_, whatever).

Dario Solera
  • 5,694
  • 3
  • 29
  • 34
0

It's more normal in C++ for members to be initialised on construction using initialiser.

To do that, you have to use a different name to the name of the member variable.

So even though I'd use Foo(int x) { this.x = x; } in Java, I wouldn't in C++.

The real smell might be the lack of use of initialisers and methods which do nothing other than mutating member variables, rather than the use of the this -> x itself.

Anyone know why it's universal practice in every C++ shop I've been in to use different names for constructor arguments to the member variables when using with initialisers? were there some C++ compilers which didn't support it?

Pete Kirkham
  • 48,893
  • 5
  • 92
  • 171
  • 1
    No you don't: Foo::Foo(int x) : x(x) { } // works as intended, the first and third x are the argument, the second x is this->x – MSalters Jun 29 '09 at 12:45
0
class MyClass
{
public:
  int m_x;
  void f(int p_x);
};


void MyClass::f(int p_x)
{
  m_x = p_x;
}

...is my preferred way using scope prefixes. m_ for member, p_ for parameter (some use a_ for argument instead), g_ for global and sometimes l_ for local if it helps readability.

If you have two variables that deserve the same name then this can help a lot and avoids having to make up some random variation on its meaning just to avoid redefinition. Or even worse, the dreaded 'x2, x3, x4, etc'...

Dan Brown
  • 111
  • 1
  • 1
  • 6
  • I have often seen p_ used to indicate a pointer in c++ which could be confusing here. – g . Jun 29 '09 at 10:00
0

I don't like using "this" because it's atavistic. If you're programming in good old C (remember C?), and you want to mimic some of the characteristics of OOP, you create a struct with several members (these are analogous to the properties of your object) and you create a set of functions which all take a pointer to that struct as their first argument (these are analogous to the methods of that object).

(I think this typedef syntax is correct but it's been a while...)

typedef struct _myclass
{
   int _x;
} MyClass;

void f(MyClass this, int x)
{
   this->_x = x;
}

In fact I believe older C++ compilers would actually compile your code to the above form and then just pass it to the C compiler. In other words -- C++ to some extent was just syntactic sugar. So I'm not sure why anyone would want to program in C++ and go back to explicitly using "this" in code -- maybe it's "syntactic Nutrisweet"

eeeeaaii
  • 3,372
  • 5
  • 30
  • 36
  • Well, it has use in clarifying something used is a member rather than a local variable. Most IDEs highlight members with different colors, but even there, `this->name` is much more prominent than a dark purple color. I don't think people prefer the "this" style for atavistic reasons. They find it to be more readable. You'll probably find what you've worked with most to benefit you the most when making new code, and when working with old code, sticking to the style chosen is wise. – user904963 Nov 30 '21 at 13:04
0

Today, most IDE editors color your variables to indicate class members of local variables. Thus, IMO, neither prefixes or 'this->' should be required for readability.

Thomas Fauskanger
  • 2,536
  • 1
  • 27
  • 42
-2

If you have a problem with naming conventions you can try to use something like the folowing.

class tea
{
public:
    int cup;
    int spoon;
    tea(int cups, int spoons);
};

or

class tea
{
public:
    int cup;
    int spoon;
    tea(int drink, int sugar);
};

I think you got the idea. It's basically naming the variables different but "same" in the logical sense. I hope it helps.

Secko
  • 7,664
  • 5
  • 31
  • 37
  • I mistook the question for something else. Now I see that you really wanted to know another approach to the notation. – Secko Jun 29 '09 at 15:44