59

I am working on someone else code in C++, and I found a weird call to a certain function func(). Here is an example:

if(condition)
    func();
else
    (*this).func();

What is the difference between func() and (*this).func()?

What are the cases where the call to func() and (*this).func() will execute different code?

In my case, func() is not a macro. It is a virtual function in the base class, with an implementation in both base and derived class, and no free func(). The if is located in a method in the base class.

gtatr
  • 6,947
  • 1
  • 17
  • 27

4 Answers4

49

There actually is a difference, but in a very non-trivial context. Consider this code:

void func ( )
{
    std::cout << "Free function" << std::endl;
}

template <typename Derived>
struct test : Derived
{
    void f ( )
    {
        func(); // 1
        this->func(); // 2
    }
};

struct derived
{
    void func ( )
    {
        std::cout << "Method" << std::endl;
    }
};

test<derived> t;

Now, if we call t.f(), the first line of test::f will invoke the free function func, while the second line will call derived::func.

lisyarus
  • 15,025
  • 3
  • 43
  • 68
31

It is impossible to tell from the snippet but possibly there are two callable objects called func(). The (*this).func(); makes sure the member function is called.

A callable object could be (for example) a functor or a lambda expression:

functor

struct func_type
{
    void operator()() const { /* do stuff */ }
};

func_type func; // called using func();

lambda

auto func = [](){ /* do stuff */ }; // called using func();

For example:

#include <iostream>

class A
{
public:

    // member 
    void func() { std::cout << "member function" << '\n'; }

    void other()
    {
        // lambda
        auto func = [](){ std::cout << "lambda function" << '\n'; };

        func(); // calls lambda

        (*this).func(); // calls member
    }
};

int main()
{
    A a;
    a.other();
}

Output:

lambda function
member function
Galik
  • 47,303
  • 4
  • 80
  • 117
  • FTR, I had to overcome some inner resistance to upvote this answer and not downvote or edit away its misuse of the word [functor](https://en.wikipedia.org/wiki/Functor). Since _function object_ is a conventional standard meaning of the word _functor_ in the context of C++, what right have I to do that... still, just saying. I always cringe a bit when I see the word used this way. – leftaroundabout Aug 04 '16 at 19:34
  • @leftaroundabout I think many C++ programmers familiar with category theory (including me) feel the same internal rant. But that's the accepted and widespread terminology, we have to accept it. – lisyarus Aug 09 '16 at 19:54
17

Another case when those two lines will call different functions:

#include <iostream>

namespace B
{ void foo() { std::cout << "namespace\n"; } }

struct A { 
  void foo() { std::cout << "member\n"; }

  void bar()
  {
      using B::foo;
      foo();
      (*this).foo();
  }
};

int main () 
{
    A a;
    a.bar();
}
Revolver_Ocelot
  • 8,609
  • 3
  • 30
  • 48
12

With type dependent name, it may be different:

void func() { std::cout << "::func()\n"; }

struct S {
    void func() const { std::cout << "S::func()\n"; }
};

template <typename T>
struct C : T
{
    void foo() const {
        func();         // Call ::func
        (*this).func(); // Call S::func
    }
};

Demo

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • I've suddenly forgotten all my past CRTPs... Does this just do the same thing as `static_cast(this)->func()`? I just assumed the latter was strictly needed, as it's used in examples so often, but now I'm wondering why if `this->func()` works just as well. I suspect there's another reason I'm not seeing. – underscore_d Aug 05 '16 at 11:00
  • @underscore_d: The important part is *dependent name*. `func()` doesn't depend of `T` whereas `(*this).func()`, `this->func()` or `T::func()` does depend of T. – Jarod42 Aug 05 '16 at 11:07