Sergey Ostrovsky on 20 Oct 2003 23:21:02 -0400


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: Re:[PLUG] C++/*this


In earlier editions of his book Stroustrup was much closer to real
programmers
( or he wanted to be understood ? ). Back then he tried to teach C guys C++.
It was explained how things are implemented, and WHY. The picture was
complete and logical.
Too bad, it's missing now. I realize that compiler technology changed
things,
and now you can generate code that doesn't insert a VMT pointer in an
object,
but use "thunks" ( I don't even know what that is ... ), but that model of
implementation
was perfect in its completeness, and you'd see how the whole thing ticks.
[ Hey, Kevin ]

Sergey.

----- Original Message ----- 
From: "Kevin Brosius" <cobra@compuserve.com>
To: "PLUG" <plug@lists.phillylinux.org>
Sent: Monday, October 20, 2003 10:27 PM
Subject: Re:[PLUG] C++/*this


> > Hi, long time no post. I have a C++ question, hopefully someone can
> > direct me to some good documentation.
> >
> > I have always understood that the "this" pointer accessible in
non-static
> > member functions of C++ objects (classes, structs or unions) is actually
> > an implicit argument added by the compiler.
> >
> >    Example:
> >
> >
> >          void Object::Function();
> >       is actually:
> >          void Object::Function(Object *this);
> >
> >
> >       so when you do this:
> >          Object ob;
> >          ob.foo();
> >
> >
> >       it can be thought of as:
> >          Object ob;
> >          Object::foo(ob);
> >
> >
> > This has always made sense to me. Since there is only one instantiation
> > of all member functions of an object, and these functions are not stored
> > as a part of the object, the function must have the *this pointer as an
> > implicit argument so that the function has access to the object's other
> > members. It also makes sense that static member functions, since they
> > do not need an object from which they are called, don't get the implicit
> > *this pointer (this would defeat the purpose of making the function
> > static).
> >
>
> You are closer to correct, I think.  I'm less than impressed with
> Stroustrup's coverage of implementation details like this, though.  (See
> comments later.)
>
> >
> > My instructor seems to think otherwise. Here is the explination I
> > was given:
> >
> >    All classes, structs and unions contain a *this pointer that
> >    references itself.  The object also contains pointers to the object
> >    member functions, therefore when calling a member function in an
> >    object the member function has access to the *this pointer.
> >
>
> I don't see any evidence that objects contain a copy of *this
> themselves, from Stroustrup.  And really, there's no need.  The storage
> location for the object is generally equivalent to *this.  Think of it
> this way, the object address equals *this, for non-static objects.  The
> compiler/linker tracks storage location, and resolves it at link time.
> It's not needed to be a member of the object.
>
> >
> >    Example:
> >
> >
> >       class Foo {
> >          private:
> >             int x;
> >
> >
> >          public:
> >             void setx(int);
> >       };
> >
> >
> >       Foo::setx(int) is instantiated only once and each object of type
> >       Foo has a function pointer to setx:
> >
> >
> >          Basically, breaking down what he said results in an object
> >          that "looks" like this:
> >
> >
> >          Foo {
> >             private:
> >                int x;
> >                Foo *this;
> >
> >
> >             public:
> >                void (*setx)(int); // this is the pointer to
Foo::setx(int);
> >          };
> >
> >
> >
> > This makes no sense to me. First there is the question of how does the
> > function (which is instantiated only once, which I know to be true) know
> > which object is "calling" it? Is there a way for a function (any
> > function) to "know" what object it was called from other than providing
> > it with a pointer to that object?
> >
> > Furthur, a simple sizeof() test shows that this (the instructor's idea
> > of how an object is created and stored) can't be true unless sizeof()
> > doesn't return the true size of an object (which would be VERY bad
> > especially if you tried to combine a malloc() call to get the required
> > memory instead of new).
> >
> > By using the simple Foo class above, with only one private data member
> > (x), and one public member function (void setx(int)), I see that the
> > sizeof(Foo) is 4 (which happens to be sizeof(int)). Is my instructor
> > full of it or am I missing something here?
> >
> > If I have it wrong, please someone point me to some documentation that
> > shows me exactly how a class' member functions (non-static) "know" which
> > object has called them and where they get *this.
>
>
> Well, you might want to think of it from a usage standpoint.  I think
> you'll find that the functions don't always need a *this pointer.  It
> depends on the implementation.  For example:
>
>       class Foo {
>
>          public:
>             void print(void) { printf("Hello World"); };
>       };
>
> If I call an instance of the above, what happens?
>
>    Foo foo;
>    foo.print();
>
> I'd bet most recent compilers don't pass *this for the above case.  It's
> unneeded for the implementation.
>
> How about:
>
>       class Foo {
>          private:
>             int x;
>
>
>          public:
>             void setx(int a) { x = a; };
>       };
>
> calling:
>
>    Foo foo;
>    foo.setx(5);
>
> Now, in this case I'd bet you are correct, meaning this case behaves
> like "setx(*this, 5)".  But here's where I think your instructor is
> wrong.  There's no need for the object to contain the *this pointer.
> The compiler can determine the object referred to by the usage.  The
> 'foo.' refers to the object, tracking the *this value, so to speak.  If
> it's needed for the function call, to access object members, then the
> compiler passes it on call.  If not, we don't need to pass the *this
> value to the function call.
>
> Stroustrup says
>   "In a nonstatic member function, the keyword 'this' is a pointer to
> the object for which the function was invoked.  In a non-const member
> function of class X, the type of 'this' is X*." [2]
> It doesn't say a whole lot more about how that is implemented, but I
> think it fits the description I gave above, and what you thought was
> correct.  I suppose it is possible that a larger overhead compiler might
> implement what your instructor suggests.  Possibly he is familiar with
> some early implementation that used table lookup heavily.
>
> -- 
> Kevin
>
> [1] The C++ Programming Language, Special Edition (3rd. ed., Jan 2003).
> Bjarne Stroustrup. p.231.
>
___________________________________________________________________________
> Philadelphia Linux Users Group         -- 
http://www.phillylinux.org
> Announcements -
http://lists.phillylinux.org/mailman/listinfo/plug-announce
> General Discussion  -- 
http://lists.phillylinux.org/mailman/listinfo/plug

___________________________________________________________________________
Philadelphia Linux Users Group         --        http://www.phillylinux.org
Announcements - http://lists.phillylinux.org/mailman/listinfo/plug-announce
General Discussion  --   http://lists.phillylinux.org/mailman/listinfo/plug