Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Excessive use of `this` in C++ [duplicate]

Tags:

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.

like image 701
SmacL Avatar asked Jun 29 '09 09:06

SmacL


1 Answers

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; } 
like image 160
bltxd Avatar answered Oct 26 '22 23:10

bltxd