C++ Internals handling this pointer

Discussion in 'C++' started by mailtogops@gmail.com, Dec 8, 2005.

  1. Guest

    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
    , Dec 8, 2005
    #1
    1. Advertising

  2. > 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
    Niels Dybdahl, Dec 8, 2005
    #2
    1. Advertising

  3. 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.
    Neelesh Bodas, Dec 8, 2005
    #3
  4. 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
    Niklas Norrthon, Dec 8, 2005
    #4
  5. Guest

    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
    , Dec 8, 2005
    #5
  6. 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
    Neelesh Bodas, Dec 8, 2005
    #6
  7. Guest

    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
    , Dec 9, 2005
    #7
  8. * :
    > 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/win32cpptut/special/pointers/ch_01.pdf

    http://home.no.net/dubjai/win32cpptut/special/pointers/ch_01_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?
    Alf P. Steinbach, Dec 9, 2005
    #8
  9. 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
    Niklas Norrthon, Dec 12, 2005
    #9
  10. Guest

    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
    , Dec 13, 2005
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Abhishek Srivastava

    Good book on the asp.net internals?

    Abhishek Srivastava, Apr 21, 2004, in forum: ASP .Net
    Replies:
    2
    Views:
    619
    Alvin Bruney [MVP]
    Apr 21, 2004
  2. Jobs Gooogle
    Replies:
    2
    Views:
    471
    Patricia Shanahan
    May 11, 2007
  3. Jobs Gooogle
    Replies:
    1
    Views:
    312
    Victor Bazarov
    May 10, 2007
  4. Jobs Gooogle

    .Net VC++ Java C++ Windows Internals Unix Internals

    Jobs Gooogle, May 10, 2007, in forum: C Programming
    Replies:
    0
    Views:
    351
    Jobs Gooogle
    May 10, 2007
  5. Jobs Gooogle
    Replies:
    0
    Views:
    121
    Jobs Gooogle
    May 10, 2007
Loading...

Share This Page