Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should I use this->functionname() over classname::functionname() for calling member functions?

I've been looking over some example code which uses both this->functionname() and classname::functionname() to call functions in the same class.

Is there actually a difference between these two methods?

Also, is there a difference between these methods and just simply calling the function using functionname()?

Thanks.

like image 735
rowanphilip Avatar asked Jul 25 '16 09:07

rowanphilip


3 Answers

As usual in C++, thing's are less simple than you might think.

There are three ways to call member functions.

  1. just call the function: foo();
  2. call with this: this->foo();
  3. use the class's name: classname::f();

Numbers #1 and #2 are equivalent, some people prefer #2 because it's clearer that this is a member function and not a global function (these people are in a minority).

Whether #3 differs from #1 and #2 depends on whether the function called is a virtual function. If it's non-virtual there is no difference. If it is virtual and there's a more derived override of this function then #1 and #2 will called the derived function and #3 will call the override that exists in this class (or if there is no override in this class, the closest super-class).

The exception to the previous paragraph is when the call-site is in a constructor or a destructor. In this case, even if the function is virtual #1 and #2 will behave the same as #3 (call the override in this, or the closest super-class).

In addition if the function is static then #2 is invalid and #1 and #3 are equivalent when called from within the class but #3 is needed when called from outside the class.

I hope I didn't miss anything :)

Things I missed:

  • this may be needed if the function is hidden by a global re-declared inside the calling function. See @Dutow's answer.
  • this can be useful when dealing with two phase lookup (when templates are involved). Thanks to @Alejandro for his comment.
  • I'm guessing that using using may throw some more mud in the water but I can't be bothered to look into it at the moment (caveat emptor).

Indeed, not as simple as one might think...

like image 146
Motti Avatar answered Oct 27 '22 03:10

Motti


Usually? They are the same. But depending on the context, they might mean different things.

For example, consider the following extreme example (don't do this in a real project!):

void f() { std::cout << "f" << std::endl; }

class Cl {
public:
    void f() { std::cout << "Cl::f" << std::endl;  }
    void g() { 
        struct Cl {
            static void f() { std::cout << "inside Cl::f" << std::endl; }
        };
        void f();  

        f(); 
        Cl::f();
        this->f();
    }
};

int main()
{
    Cl a;
    a.g();

    return 0;

}

In this, the declaration of the global f shadows the member method f, resulting in the program outputting f instead of Cl::f.

The local struct Cl also shadows it's own typename, resulting in Cl::f() calling it's static f method.

Only calling this->f() explicitly results in calling Cl::f.

The variant with the typename is also commonly used when you want to call methods in the parent class when using inheritance and overriding virtual methods - but that's technically not the same class.

like image 3
Dutow Avatar answered Oct 27 '22 03:10

Dutow


I think one reason to use this is in this scenario. E.g.

class A
{
public:
    void foo() { this->doFoo(); } //equivalent to just doFoo();
    void foo2() { Abstract::doFoo(); }
private:
    virtual void doFoo() { /* do stuff */ }
};

In the snippet when calling foo it will invoke doFoo in the most derived class. When calling foo2 it will always call base implementation even if it was overriden.

like image 1
Resurrection Avatar answered Oct 27 '22 03:10

Resurrection