Kevin Brosius on 20 Oct 2003 22:28:02 -0400


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

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