Page 1 of 1

Question about this pointer

Posted: Wed Jun 13, 2007 8:02 pm
by Dances
Maybe I don't have a clue what I'm talking about and completely misunderstand this... but....

say I have a class called.... myclass.

Code: Select all

class myclass
{
    //I r class code stuffs n00b
};
And in this I have a function called.... function.

Code: Select all

class myclass
{
    public:
       void function();
};
and another function... called.... anotherFunction....

Code: Select all

class myclass
{
    public:
       void function();
       void anotherFunction();
};
and I declare function

Code: Select all

void function()
{
   //I r function code stuffs n00b
}
and in anotherFunction I want to call function...

What is the difference between using this and calling the class....

Code: Select all

void anotherFunction()
{
   this->function();
}
and

Code: Select all

void anotherFunction()
{
   myclass::function();
}
They both do the same thing, don't they? Is one better than the other at certain times? Sorry if I have this completely wrong and this is used for something entirely different ^.^

Posted: Wed Jun 13, 2007 8:13 pm
by bitplane
if i make a "newclass" derived from "myclass" and override function(), myclass::function() will call myclass::function(), but this->function() will call newclass::function().
also, i dont think there's any difference between "this->function()" and "function()"

Posted: Thu Jun 14, 2007 12:05 am
by omar shaaban
it is like 1+1=2 and 4-2=2 ..... :lol:

Posted: Thu Jun 14, 2007 12:32 am
by eneru
bitplane wrote: also, i dont think there's any difference between "this->function()" and "function()"
there is no differences, but the first is much clearer i think :) (more especially for class arguments)

Posted: Thu Jun 14, 2007 1:42 am
by olivehehe_03
Just remember a few things about the full name of functions. In your example, the full name of 'function()' is 'myclass::function()'. What this means is that if you want to call function from outside the class you need to use 'myclass::function()', which tells the program to run the function called 'function()' which is in the class 'myclass'. But if you want to call the function from inside the class, the 'myclass::' part is assumed, or better yet, can be replaced with 'this->'. Hope that made sense :P

Posted: Thu Jun 14, 2007 6:07 am
by Dances
So gathering from what you guys are saying, especially bitplane, there is no consequence in *not* using this-> EXCEPT when you overload a class?

Posted: Thu Jun 14, 2007 6:24 am
by Saturn
bitplane wrote:if i make a "newclass" derived from "myclass" and override function(), myclass::function() will call myclass::function(), but this->function() will call newclass::function().
also, i dont think there's any difference between "this->function()" and "function()"
That's not right, because the functions are not virtual. this->function(), function(), and myclass::function() do all the same.
When you want to have the behaviour bitplane described, then you have to make the member function function() virtual.

@olivehehe_03, myclass::function() is a member function, you need an instance of myclass to call this function, so just calling myclass::function(); won't work, because this function is not static.

@eneru, it's a taste question, but most C++ coding styles don't use this explicitly in cases it is clear. Calling member functions inside other member functions on the same instance is more or less the default case. Instead use of other functions should be made obvious. Like when calling a function in global space to call it this way ::myglobalfunction() or when it is inside a namespace prepend it with the namespace. This is more helpful to a reader of the source code, as it carries more informations.

Posted: Thu Jun 14, 2007 7:52 am
by hybrid
Making the method virtual is even a step further than described - for plain overwriting of methods bitplane is right. If you make a method virtual you will not just overwrite the method, but also establish an automatic choice of the right method when calling it from base class pointers. So if you have a derived class B : A, with A and B having virtual method do(), and you take a base class pointer A* ptr = &Bobject, you can call ptr->do() and the method from B will be executed. So the pointer will keep the information that it is in fact a B object and it's virtual methods become precedence over those from A. For non-virtual methods you would call those from A if you have a pointer to an A object.
However, this will happen with or without this-> prefix, so I don't think that the this-> prefix is useful. Some people tend to use it for initialiser lists (such that parameters and memeber variables can have the same name), but I think it's much easier and better readable to use different parameter names.

Posted: Thu Jun 14, 2007 8:26 am
by vitek
you need an instance of myclass to call this function, so just calling myclass::function(); won't work, because this function is not static.
Wrong. You can most definitely explicitly invoke a member function using that syntax. Heck, you can even use that syntax from outside the class. Using the code below, it would be totally legal to write b.A::foo().

Code: Select all

#include <stdio.h>

struct A
{
  /*virtual*/ void foo()
  {
    printf("A::foo!\n");
  }

  void bar()
  {
    printf("A::bar!\n");

    A::foo();
    foo();
    this->foo();
  }
};

struct B : A
{
  void foo()
  {
    printf("B::foo!\n");
  }
};

int main()
{
  B b;
  b.bar();

  return 0;
}
In the above testcase, A::foo(), foo() and this->foo() are equivalent. If foo() was made virtual then the A::foo() will explicitly invoke the method in class A. The other two will invoke the virtual foo() in the derived class.

There is a case when using templates that you need to use the this pointer explicitly. I'd be willing to bet that there are other cases. This is just one example

Code: Select all

 template <class T>
 class A {
 public:
   void foo() { }
 };
 
 template <class T>
 class D : public B<T> {
 public:
   void bar()
   {
     this->foo();
   }
 }; 
If you don't explicitly say this-> it shouldn't compile. This is because the compiler isn't supposed to look in a dependent base class for a non-dependent name.

Travis
Travis

Posted: Thu Jun 14, 2007 8:48 am
by Saturn
@vitek, I know this but it is not what I wrote:

Code: Select all

myclass::function();
And this doesn't work obviously.
Of course you can do what you write. Sometimes had to use it myself already.

@hybrid, here is a short mock up to illustrate this:

Code: Select all

#include <iostream>

class Base
{
public:
	void function()
	{
		std::cout << "Base::function" << std::endl;
	}

	virtual void virtualFunction()
	{
		std::cout << "Base::virtualFunction" << std::endl;
	}

	void callFunction()
	{
		std::cout << "calling function :  ";
		function();
	}

	void callVirtualFunction()
	{
		std::cout << "calling virtualFunction :  ";
		virtualFunction();
	}
};

class Derived : public Base
{
public:
	void function()
	{
		std::cout << "Derived::function" << std::endl;
	}

	virtual void virtualFunction()
	{
		std::cout << "Derived::virtualFunction" << std::endl;
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	Base* b = new Base();
	Derived* d = new Derived();

	b->callFunction();
	b->callVirtualFunction();

	d->callFunction();
	d->callVirtualFunction();

	return 0;
}
The output is:

Code: Select all

calling function :  Base::function
calling virtualFunction :  Base::virtualFunction
calling function :  Base::function
calling virtualFunction :  Derived::virtualFunction
As you can see Base::function has been called by the non-overridden Base::callFunction for the Derived instance.
This is the situation as described by Dances in the initial post. Overriding non-virtual functions (if overriding is the right word here anyway) is very bad style. It only confuses, better give the functions different names then.

Posted: Thu Jun 14, 2007 9:22 am
by hybrid
The effect is due to the first call to a base class method, which in turn calls the second base class method. Obviously, you did not want to call any other function instead of the original one in your callFunction method - the compiler finds a non-virtual method call and replaces it by the class method's entry point. However, if you call the function() method directly with the two pointers you'll get the expected output where each object calls its own method, being virtual or not.

Posted: Thu Jun 14, 2007 9:55 am
by omar shaaban
why dont u just call the function

Code: Select all

function();

and that's all folks :?

Posted: Thu Jun 14, 2007 10:50 am
by eneru
Saturn wrote:@eneru, it's a taste question, but most C++ coding styles don't use this explicitly in cases it is clear. Calling member functions inside other member functions on the same instance is more or less the default case. Instead use of other functions should be made obvious. Like when calling a function in global space to call it this way ::myglobalfunction() or when it is inside a namespace prepend it with the namespace. This is more helpful to a reader of the source code, as it carries more informations.
well, if it is a class argument it may be clear enough (though i still use the this pointer), but by example in the code of the CGUIImage by example you can see things that are not directly arguments of the class, then you (or I at least) wonder "WTH did they come from, there is no argument with this name", look at the class, nothing, look at the upper class (IGUIImage), still nothing, and finally find out by looking at the IGUIElement class (if i remember well) :P
When "this" is used you don't even start to wonder about these questions, so I recommend it ^^