Question about this pointer

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Dances
Posts: 454
Joined: Sat Jul 02, 2005 1:45 am
Location: Canada
Contact:

Question about this pointer

Post 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 ^.^
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post 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()"
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
omar shaaban
Posts: 616
Joined: Wed Nov 01, 2006 6:26 pm
Location: Cairo,Egypt
Contact:

Post by omar shaaban »

it is like 1+1=2 and 4-2=2 ..... :lol:
eneru
Posts: 40
Joined: Tue Apr 10, 2007 8:38 am

Post 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)
olivehehe_03
Posts: 157
Joined: Tue Mar 20, 2007 8:30 am

Post 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
Tell me what you cherish most. Give me the pleasure of taking it away.
Dances
Posts: 454
Joined: Sat Jul 02, 2005 1:45 am
Location: Canada
Contact:

Post 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?
Saturn
Posts: 418
Joined: Mon Sep 25, 2006 5:58 pm

Post 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.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post 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.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post 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
Saturn
Posts: 418
Joined: Mon Sep 25, 2006 5:58 pm

Post 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.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post 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.
omar shaaban
Posts: 616
Joined: Wed Nov 01, 2006 6:26 pm
Location: Cairo,Egypt
Contact:

Post by omar shaaban »

why dont u just call the function

Code: Select all

function();

and that's all folks :?
eneru
Posts: 40
Joined: Tue Apr 10, 2007 8:38 am

Post 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 ^^
Post Reply