Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > C++ Internals handling this pointer

Reply
Thread Tools

C++ Internals handling this pointer

 
 
mailtogops@gmail.com
Guest
Posts: n/a
 
      12-08-2005
Hi,

I have this question in mind for many years..

C++ class provides encapsulation which encapsulate its members and
member function.

class Experiment
{
private:

int _experient;

public:

void ExpFun()
{
// Code here
}

};

Here ExpFun() is a member function, so at runtime this member function
shall have a memory where the function execuatble code reside.
Obviously there should be only one copy (Assume void ExpFun() is not
inline function) of ExpFun() in memory.

But I can create many objects for Experiment class

Experiment e1,e2, e3;

Logically we are calling the function like this

e1.ExpFun();
e2.ExpFun();
e3.ExpFun();


When the function is called, what happens?. Howcome the ExpFun() works
exactly with the corresponding member variables of the object?. Where
this pointer has been passed to ExpFun()?.

I would appreciate if someone answer me or guide a good book to get
idea about this..

Thanks for you time.

Thanks & Regards,

Gopal

 
Reply With Quote
 
 
 
 
Niels Dybdahl
Guest
Posts: n/a
 
      12-08-2005
> When the function is called, what happens?. Howcome the ExpFun() works
> exactly with the corresponding member variables of the object?. Where
> this pointer has been passed to ExpFun()?.


Yes. The pointer to the object (this) is passed to the function. So the
compiler implements a function which actually takes one more parameter than
you have specified.

Niels Dybdahl


 
Reply With Quote
 
 
 
 
Neelesh Bodas
Guest
Posts: n/a
 
      12-08-2005
(E-Mail Removed) wrote:
> Hi,
>
> class Experiment
> {
> private:
>
> int _experient;
>
> public:
>
> void ExpFun()
> {
> // Code here
> }
>
> };
>
> Here ExpFun() is a member function, so at runtime this member function
> shall have a memory where the function execuatble code reside.
> Obviously there should be only one copy (Assume void ExpFun() is not
> inline function) of ExpFun() in memory.


By the way, functions defined inside the class are by default "inline".
(Of course that doesnot mean that they will _always_ be inlined)
So you could define the same function outside the class.

>
> But I can create many objects for Experiment class
>
> Experiment e1,e2, e3;
>
> Logically we are calling the function like this
>
> e1.ExpFun();
> e2.ExpFun();
> e3.ExpFun();
>
>
> When the function is called, what happens?. Howcome the ExpFun() works
> exactly with the corresponding member variables of the object?. Where
> this pointer has been passed to ExpFun()?.


When a non-static member function is called, the "this" pointer is
_always_ passed as the "hidden" argument. So Suppose your member
function X::foo has the prototype :

void X::foo(int, int) ;

then when you say
p.foo(14,20)
for some object p of class X, the function foo is actually invoked with
three parameters (as an example : )

1) the this pointer
2) first argument's copy (14)
3) second argument's copy (20)


> I would appreciate if someone answer me or guide a good book to get
> idea about this..


You can actually try to compile a sample C++ program to generate
assembly code and look at it yourself.

 
Reply With Quote
 
Niklas Norrthon
Guest
Posts: n/a
 
      12-08-2005
http://www.velocityreviews.com/forums/(E-Mail Removed) writes:

> Hi,
>
> I have this question in mind for many years..
>
> C++ class provides encapsulation which encapsulate its members and
> member function.
>
> class Experiment
> {
> private:
>
> int _experient;
>
> public:
>
> void ExpFun()
> {
> // Code here
> }
>
> };
>
> Here ExpFun() is a member function, so at runtime this member function
> shall have a memory where the function execuatble code reside.
> Obviously there should be only one copy (Assume void ExpFun() is not
> inline function) of ExpFun() in memory.
>
> But I can create many objects for Experiment class
>
> Experiment e1,e2, e3;
>
> Logically we are calling the function like this
>
> e1.ExpFun();
> e2.ExpFun();
> e3.ExpFun();
>
>
> When the function is called, what happens?. Howcome the ExpFun() works
> exactly with the corresponding member variables of the object?. Where
> this pointer has been passed to ExpFun()?.
>
> I would appreciate if someone answer me or guide a good book to get
> idea about this..


Short answer first: By magic. The standard doesn't say how things should
work. The internals is implementation specific.

Below is a description of one possible way to implement the C++ object
model, which might not be 100% correct on any single existing platform
but should give you an idea on how things work in practice.

The standard speaks about different storage classes of memory, and there
are three of them: static, automatic, and free store.

Static memory is initialized at the beginning of a program, and is
never destroyed, deallocated or any such thing. Objects can be placed
in static memory, either by defining them at namespace scope, i.e
outside any function, or struct (when I say struct it also applies to
classes), or by using the static keyword inside functions and structs.

Executable code also resides in static memory. This applies to normal
functions as well as member functions, constructors, destructors etc.
So when you say something like:

struct Experiment {
void ExpFun() { /* code here */ }
};

The compiler generates the code at one place in the static memory and
label it with a name according to an implementation specific scheme.
For example it could use the name __struct_Experiment_void_ExpFun_void__
for this function.

When you later in your code call it with:

int main()
{
Experiment e;
e.ExpFun();
}

The compiler knows that e is of the type Experiment, so it just translate
the code to call the function named __struct_Experiment_void_ExpFun_void__,
almost as you would have said:

extern __struct_Experiment_void_ExpFun_void__();

int main()
{
__struct_Experiment_void_ExpFun_void__();
}

The exact naming scheme is specific to each implementation, but it's usually
quite easy to list the names. On unix systems there is the nm utility and
I guess Win32's dumpbin is similar. Sometimes the "mangled" names show up
in error messages during the linking phase too, so it can be useful to
have an idea of how things work.

So reamins the question of how the function knows where the member variables
are stored.

Suppose now that we have the following:

struct Experiment {
int member;
static int member_static;

Experiment() : member(0) { }
void ExpFun() { member_static = member; }
void ExpFun(int x) { member = x; }
static void ExpStaticFun(int x);
};

int Experiment::member_static = 42;

The compiler takes this apart and generates code for the following:

struct Experiment {
int member;
};

int __struct_Experiment_member_static__ = 42;

void __struct_Experiment_ctor_void__(Experiment * const this)
{
this->member = 0;
}

void __struct_Experiment_ExpFun_void__(Experiment * const this)
{
__struct_Experiment_member_static__ = this->member;
}

void __struct_Experiment_ExpFun_int__(Experiment * const this, int x)
{
this->member = x;
}

void __struct_static_Experiment_ExpFun_int__(int x)
{
__struct_Experiment_member_static__ = x;
}

All member functions and static member variables are stripped out
from the struct, leaving an old fashoned C struct behind. Taking
the sizeof a struct reflects this. It does not matter how many
member functions a struct has, the size is the same.

The member functions are renamed and placed next to all other
functions in the static memory, and a function argument named
"this", is automatically added, which holds a pointer to the
object the function will operate on. Note that it is only for
non static member functions that the "this" argument is added.

When a client of the struct later says:

int main()
{
Experiment e;
e.ExpFun();
e.ExpFun(12);
e.ExpStaticFun(13);
Experiment::ExpStaticFun(14);
}

It gets translated to:

int main()
{
Experiment e; /* sizeof e is allocated in automatic memory (stack) */
__struct_Experiment_ctor_void__(&e);
__struct_Experiment_ExpFun_void__(&e);
__struct_Experiment_ExpFun_int__(&e, 12);
__struct_static_Experiment_ExpFun_int__(13);
__struct_static_Experiment_ExpFun_int__(14);
}

I hope you get an idea on how things usually are implemented.
Play with your compiler and tools to see how it works in your
implementation.

/Niklas Norrthon
 
Reply With Quote
 
mailtogops@gmail.com
Guest
Posts: n/a
 
      12-08-2005
Hi All,

Thanks for the information. But furthur I would like ot dig more..

The current object pointer always passed to the member function.
Suppose consider the class

class Experiment
{
public:
int _no;
void setNo(int i)
{
_no = i;
}
};

In the above code, I have assigned

_no = i;

So during compilation, the compiler must convert this code to represent
internally like

this->_no = i;

Is this right?

Thanks & Regards,

Gopal

 
Reply With Quote
 
Neelesh Bodas
Guest
Posts: n/a
 
      12-08-2005

(E-Mail Removed) wrote:
> Hi All,
>
> In the above code, I have assigned
>
> _no = i;
>
> So during compilation, the compiler must convert this code to represent
> internally like
>
> this->_no = i;
>
> Is this right?


Yes, thats what the compiler does.
Look up any descent book on C++, it should talk about this. Eg. TC++PL
10.2.7

>
> Thanks & Regards,
>
> Gopal


 
Reply With Quote
 
mailtogops@gmail.com
Guest
Posts: n/a
 
      12-09-2005
Hi Niklas Norrthon,

Thanks a lot for detailed explanation..

Could you please point out how the compiler manages dynamic
call(virtual functions/polymorphism) with the 'this' pointer, which
would complete this discussion..

Thanks & Regards,

Gopal

 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      12-09-2005
* (E-Mail Removed):
> Hi Niklas Norrthon,
>
> Thanks a lot for detailed explanation..
>
> Could you please point out how the compiler manages dynamic
> call(virtual functions/polymorphism) with the 'this' pointer, which
> would complete this discussion..


See section 1.2 "Run-time polymorphism" of

http://home.no.net/dubjai/win32cpptu...ters/ch_01.pdf

http://home.no.net/dubjai/win32cpptu...1_examples.zip

Hth.,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
Niklas Norrthon
Guest
Posts: n/a
 
      12-12-2005
(E-Mail Removed) writes:

> Hi Niklas Norrthon,
>
> Thanks a lot for detailed explanation..
>
> Could you please point out how the compiler manages dynamic
> call(virtual functions/polymorphism) with the 'this' pointer, which
> would complete this discussion..


By magic.

As always different compilers do it in different ways. On common
approach is to have a "virtual table (or vtable)" for each class,
and have a "virtual pointer (vptr)" included in each instance
of a class with at least one virtual function.

struct Foo
{
Foo();
virtual ~Foo() { }

void func();
virtual void grunc();

int data;
};

For the Foo class above, the compiler would generate the
functions:

__struct_Foo_ctor_void__(Foo * const this);
__struct_Foo_virtual_dtor__(Foo * const this);
__struct_Foo_void_func_void__(Foo * const this);
__struct_Foo_virtual_void_grunc_void__(Foo * const this);

The virtual table would be implemented by a global varible:

struct __Foo_vtable_t__
{
void (*__dtor__)(Foo* const);
void (*__grunc__)(Foo* const);
} __Foo_vtable__ = { __struct_Foo_virtual_dtor__,
__struct_Foo_virtual_void_grunc_void__ };

Finally, the data in a Foo object could be represented by the following:

struct Foo
{
__Foo_vtable_t__* vptr;
int data;
};

The code:

void hello(Foo* f)
{
f->func();
f->grunc();
f->Foo::grunc();
}

int main()
{
Foo x;
hello(&f);
return 0;
}

would be transformed to something like:

void hello(Foo* f)
{
__struct__Foo_void_func_void__(f);
f->vptr->__grunc__(f);
__struct__Foo_virtual_void_grunc_void__(f);
}

int main()
{
struct Foo x;
__struct_Foo_ctor_void__(f);
hello(f);
__struct_Foo_virtual_dtor__(f);
return 0;
}

When there is inheritance involved, each derived class has it's
own vtable, with overridden functions at the same places as in
the parent vtable, with additional function appended:

struct Bar : public Foo
{
virtual ~Bar() { }
virtual void beepbeep();
};

struct __Bar_vtable_t__
{
void (*__dtor__)(Foo* const);
void (*__grunc__)(Foo* const);
void (*__beepbeep__)(Foo* const);
} __Foo_vtable__ = { __struct_Bar_virtual_dtor__,
__struct_Foo_virtual_void_grunc_void__,
__struct_Bar_virtual_void_beepbeep_void__};


For functions that are not overridden the pointer in the vtable point
to the parent function.

Multiple inheritance is a little bit more involved, and virtual
inheritance even worse, so I won't talk about them here, but
when you understand normal inheritance, it's not too difficult
to understand how these work too.

/Niklas Norrthon

 
Reply With Quote
 
mailtogops@gmail.com
Guest
Posts: n/a
 
      12-13-2005
Niklas Norrthon,

Thanks a lot for your detailed explanation..

It is really nice to use usenet which is like thesaurus of knowledge
and people value..

Enjoy Learning..

Thanks and Regards,

Gopal

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
.Net VC++ Java C++ Windows Internals Unix Internals Jobs Gooogle Java 2 05-11-2007 02:23 PM
.Net VC++ Java C++ Windows Internals Unix Internals Jobs Gooogle C++ 1 05-10-2007 06:53 PM
.Net VC++ Java C++ Windows Internals Unix Internals Jobs Gooogle C Programming 0 05-10-2007 06:39 PM
.Net VC++ Java C++ Windows Internals Unix Internals Jobs Gooogle Javascript 0 05-10-2007 06:38 PM
Pointer-to-pointer-to-pointer question masood.iqbal@lycos.com C Programming 10 02-04-2005 02:57 AM



Advertisments