tags:

views:

412

answers:

14

I understand the meaning of 'this', but I can't see the use case of it.

For the following example, I should teach the compiler if the parameter is the same as member variable, and I need this pointer.

#include <iostream>

using namespace std;

class AAA {
    int x;
public:
    int hello(int x) { this->x = x;}
    int hello2(int y) {x = y;} // same as this->x = y
    int getx() {return x;}
};

int main()
{
   AAA a;
   a.hello(10); // x <- 10
   cout << a.getx();
   a.hello2(20); // x <- 20
   cout << a.getx();
}

What would be the use case for 'this' pointer other than this (contrived) example?

Added

Thanks for all the answers. Even though I make orangeoctopus' answer as accepted one, it's just because he got the most vote. I must say that all the answers are pretty useful, and give me better understanding.

+1  A: 

The this pointer is the pointer to the object itself. Consider for example the following method:


class AAA {
    int x;
public:
    int hello(int x) { some_method(this, x);}
};
Krumelur
+3  A: 

In C++ it is not used very often. However, a very common use is for example in Qt, where you create a widget which has the current object as parent. For example, a window creates a button as its child:

QButton *button = new QButton(this);
Gianni
It's not used very often? I use it a lot, it's a really important feature of OO languages.
Falmarri
Its not if compared to things like C# and the like, which need this for every member access. So it depends on your reference point.
Gianni
+10  A: 

The 'this' pointer is useful if a method of the class needs to pass the instance (this) to another function.

Patrick
+1  A: 
void somefunc(AAA* a_p)
{
   ......
}

class AAA { 
    int x; 
public: 
    int hello(int x) { this->x = x;} 
    int hello2(int y) {x = y;} // same as this.x = y 
    int getx() {return x;} 
    void DoSomething()   { somefunc(this);   }
};
James Curran
Usually I'd rather either scrap `somefunc` (put its implementation in `DoSomething()`) or call `somefunc(instAAA)` directly, depending on if `somefunc` is publicly visible or not.
Brian
+3  A: 

When passing a reference to an object within one of its methods. For instance:

struct Event
{
    EventProducer* source;
};

class SomeContrivedClass : public EventProducer
{
public:
   void CreateEvent()
   {
       Event event;
       event.source = this;
       EventManager.ProcessEvent(event);
   } 
};
Andrew Garrison
+9  A: 

It's useful if you need to pass a pointer to the current object to another function, or return it. The latter is used to allow stringing functions together:

Obj* Obj::addProperty(std::string str) {
    // do stuff
    return this;
}

obj->addProperty("foo")->addProperty("bar")->addProperty("baz");
Michael Mrozek
+12  A: 

Sometimes you want to return yourself from an operator, such as operator=

MyClass& operator=(const MyClass &rhs) {
     // assign rhs into myself

     return *this;
}
orangeoctopus
Not criticizing you, but I'm not a fan of that idiom. I know it's kind of how C and C++ have always been done, but IMO assignment operators shouldn't return a value. It's not about confusing `=` with `==` in expressions which, to the best of my memory, I've never done. It's partly just a reaction to some classic obfuscated-C-style abuses, and partly the issues with iterator ++/-- operators return-value overheads for values that are hardly ever used (the reason why we're supposed to use `++i` rather than `i++` in for loops these days).
Steve314
if you don't return a value, you can't write a = b = c, which means your type will not behave like the built in types
frankc
Also, you won't be able to do: `while(myobject = something.next())`, which is considered bad style by many. I still like it, though :).`a=b=c` is the best reason to do this.
orangeoctopus
@Steve314: I'm a fan of the idiom because it makes `operator=()` behave like `=`. I consider consistency in the use of operators to be very important.
David Thornley
@David - consistency yes, to a point, but my point is that I wish C and C++ didn't return a value from assignments in the first place. Not for user-developed code, not for libraries, and not for built-ins either. That being the case, maybe consistency isn't an absolute - e.g. why should it take precedence over such issues as only implementing what you need and will use (due to the KISS principle). Whatever you decide, it's a trade-off.
Steve314
@Steve314: I'm OK with `a=b=c;`, but I do wish `if (x=0)` was illegal. However, that's not changing in C or C++. That being the case, I'd like operators to be consistent in behavior (which means, among other things, not using `operator||` or `operator,`). I think redefining what operators mean conceptually and how they work is a Bad Idea, and that this is much more important than KISS or YAGNI.
David Thornley
@user275455, @orangeoctopus, @David - I'm OK with being able to write "a=b=c", but how that's achieved now (associativity) isn't the only way to get that. Compilers could support n-ary assignment syntax and implicitly translate into (n-1) binary assignment calls, for instance. If you're going to change one detail of a language, why assume all else must remain unchanged? Of course this isn't a serious suggestion for C or C++, though - the idea of changing something like this now... even crazier than Python changing the semantics of the division operator.
Steve314
+2  A: 

You can delete a dynamically created object by calling delete this from one of its member functions.

tsiki
And doing it can severely injure you or kill you.
zneak
Why is that? Of course it causes problems with objects created on stack, but on objects created on heap with the `new` operator, too?
tsiki
Self-deletion seems like bad style to me. People expect to be able to reference fields of the object within a method, and it would be too easy to add a reference to a field of the now non-existent object after the deletion. True, the maintainer should see the `delete this` and know better, but even so... conceptually, you still have a method call on a now non-existent object, however briefly.
Steve314
@Steve314: Self-deletion isn't bad style, if used appropriately for delayed deletion of objects. A typical use case for delated deletion are asynchronous dialogs in GUI toolkits, which should delete themselves when closed in order to prevent memory leaks. The mentioned Qt toolkit even provides a member function for this (`QObject::deleteLater()`).
lunaryorn
@Steve314: Self-deletion is also often used when implementing reference counting where deletion through a direct call of `operator delete()` is dis-allowed. In such cases deletion is performed through the member that decreases the reference count, and the destructor is made `protected` to enforce memory management through the reference counting mechanism.
Void
Many places seem to reference this FAQ on `delete this`: http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.15
tsiki
@lunaryorn - As tzikis link shows, there's a lot that can go wrong with `delete this` - e.g. what if the user created an array of controls? "QT does it" doesn't mean it's good style. The toolkit could have been written differently. Perhaps it does - depending on what that "deleteLater" method actually does.
Steve314
@Void - when implementing garbage collection, you're basically bypassing normal C++ mechanisms anyway. It's a special-case hack. That doesn't make it good style.
Steve314
@Steve314: First of all, his link says "As long as you're careful, it's OK for an object to commit suicide (delete this)". Of course, a lot can go wrong, if `delete this` is abused. But in some (probably rare) situations it is simply convenient, and working around it can be tedious. Qt was merely an example, not an argument. `QObject::deleteLater()` is as careful as the toolkit can be, the rest is the programmer's responsibility. Storing Qt objects in an array without using QPointer is an example of *not* being careful :)
lunaryorn
+1  A: 

this is implicit whenever you use a member function or variable without specifying it. Other than that, there are many, many situations in which you'll want to pass the current object to another function, or as a return value.

So, yeah, it's quite useful.

zneak
+1  A: 

Sometimes you need to refer to "this" object itself, and sometimes you may need to disambiguate in cases where a local variable or a function parameter shadows a class member:

class Foo {
  int i;

  Foo* f() {
    return this; // return the 'this' pointer
  }
  void g(){
    j(this); // pass the 'this' pointer to some function j
  }
  void h(int i) {
    this->i = i; // need to distinguish between class member 'i' and function parameter 'i'
  }
};

The two first cases (f() and g() are the most meaningful cases. The third one could be avoided just by renaming the class member variable, but there's no way around using this in the first two cases.

jalf
+1 as it condenses the main three uses in a short descriptive way. There is a fourth obscure case where `this` is needed, and that is converting a non-dependent name into a dependent name when a template derives from one of its arguments and needs to use one of its members.
David Rodríguez - dribeas
+3  A: 

Besides obtaining a pointer to your own object to pass (or return) to other functions, and resolving that an identifier is a member even if it is hidden by a local variable, there is an really contrived usage to this in template programming. That use is converting a non-dependent name into a dependent name. Templates are verified in two passes, first before actual type substitution and then again after the type substitution.

If you declare a template class that derives from one of its type parameters you need to qualify access to the base class members so that the compiler bypasses the verification in the first pass and leaves the check for the second pass:

template <typename T>
struct test : T {
   void f() {
      // print();    // 1st pass Error, print is undefined
      this->print(); // 1st pass Ok, print is dependent on T
   }
};
struct printer {
   void print() { std::cout << "print"; }
};
struct painter { 
   void paint() { std::cout << "paint"; }
};
int main() {
   test<printer> t;  // Instantiation, 2nd pass verifies that test<printer>::print is callable
   t.f();
   //test<painter> ouch; // 2nd pass error, test<painter>::print does not exist
}

The important bit is that since test inherits from T all references to this are dependent on the template argument T and as such the compiler assumes that it is correct and leaves the actual verification to the second stage. There are other solutions, like actually qualifying with the type that implements the method, as in:

template <typename T>
struct test2 : T {
   void f() {
      T::print(); // 1st pass Ok, print is dependent on T
   }
};

But this can have the unwanted side effect that the compiler will statically dispatch the call to printer::print regardless of whether printer is a virtual method or not. So with printer::print being declared virtual, if a class derives from test<print> and implements print then that final overrider will be called, while if the same class derived from test2<print> the code would call printer::print.

// assumes printer::print is virtual
struct most_derived1 : test<printer> {
   void print() { std::cout << "most derived"; }
};
struct most_derived2 : test2<printer> {
   void print() { std::cout << "most derived"; }
};
int main() {
   most_derived1 d1;
   d1.f();          // "most derived"
   most_derived2 d2;
   d2.f();          // "print"
}
David Rodríguez - dribeas
Nice answer. This is pretty common when using the CRTP idiom--in fact I had to use it just yesterday! :)
Drew Hall
+1  A: 

Another possible use case of this:

#include <iostream>
using namespace std;

class A
{
    public:
    void foo()
    {
        cout << "foo() of A\n";
    }
};

class B : A
{
    public:
    void foo()
    {
        ((A *)this)->foo(); // Same as A::foo();
        cout << "foo() of B\n";
    }
};

int main()
{
    B b;
    b.foo();
    return 0;
}
g++ this.cpp -o this
./this 
foo() of A
foo() of B
Vanni Totaro
+1  A: 

One more use of this is to prevent crashes if a method is called on a method is called on a NULL pointer (similar to the NULL object pattern):

class Foo 
{
public:
    void Fn() 
    {
        if (!this)
            return;
        ...
    }
};
...
void UseFoo(Foo* something)
{
    something->Fn(); // will not crash if Foo == NULL
}

If this is useful or not depends on the context, but I've seen it occasionally and used it myself, too.

nikie
A: 

self-assignment protection

nbourbaki