Re: Casting of pointer to member functions



"David Olsson" wrote:
You can safely cast pointer to member to other type
(which
must be poiner to member, too) only in case you intend to
cast it back before any usage. That's the only thing that
Standard guarantees you:

Thanks for the reply. My example isn't very complete nor
exact. In
reality I do cast the pointer back before making the
actual call. It is
however the cast depicted in my example code which is
giving me
problems.

Just to make sure I got you correct; the example should
compile but not
work necessarily?


The example above will compile only if /ymg compiler switch
is specified. It will make all pointers to members large
enough, so you will be able to reinterpret_cast between them
without concern. In other words, the bits that pointer is
consist of will be copied from one variable to another
without loss.

However, calling a member function through such pointer is
another story. In order call to succeed compiler makes
`this' pointer adjustments according to pointer's type
before entering member function, so member function can
safely operate on `this' pointer. For example:

------------------------------
struct A
{
void Foo(/*params*/);

// ...
};

struct B
{
void Goo(/*params*/);

// ...
};

struct C : A, B
{
// ...
};

C* pc = ...;

typedef void (C::* PCFN)();
PCFN pfn = &C::Foo;

(pc->*pfn)(/*params*/);
------------------------------

In this example layout of struct C is as following:

+------------+
| A subclass |
+------------+
| B subclass |
+------------+
| C members |
+------------+

Now, when `A::Foo' is called on C instance, then compiler
just passes pointer to C struct, since A subclass starts at
beggining of C. That's why `A::Foo' can access A's members
through `this' pointer safely.

However, compiler cannot pass pointer to C as `this' when
`B::Goo' is called, since B class starts at `sizeof(A)'
offset inside C. So, before entering `B::Goo' body, `this'
pointer must be adjusted:

// in pseudocode
B* pThis = pc + sizeof(A);
B::Goo(pThis, /*params*/);

In the above sample `sizeof(PCFN)' will be more than 4 bytes
because of `this' adjustment information stored in it.
That's why if you attempt to cast pointer of type `PCFN' to
type `void (B::*)()' for example, then compiler will issue
an error, because it cannot fit all necessary info into
destination pointer.

Now, you can enable compiler (with /ymg switch) to cast
`PCFN' to type `void (B::*)()' anyway. However, pointer to B
memeber won't contain all necessary information in order to
adjust `this' correctly, so at runtime when body of `B::Goo'
will be entered `this' pointer will incorrectly point to
start of C (i.e. A subclass). If you're lucky the call will
cause to crash and you will be able to debug it immediately.
If you're not so lucky, then the call will silently corrupt
instance of C and crash will occur somewhere else when you
least expect it.

HTH
Alex


.



Relevant Pages

  • Re: problem with memcpy and pointers/arrays confusion - again
    ... this second method is known as an explicit conversion, or cast. ... The cast, in effect, tells the compiler: ... the malloc function. ... function taking a size_t as a parameter and returning a void pointer (i.e. ...
    (comp.lang.c)
  • Re: Why the compiler applies sign extension to unsigned data?
    ... I want the value of p to be made unsigned *before* the cast. ... want the cast to generate a sign extension. ... ULONG_PTR is ULONG and casting the pointer to ULONG_PTR first is the ... on the compiler and on the knowledge of the size of the ptr variable, ...
    (microsoft.public.development.device.drivers)
  • Re: Can I Trust Pointer Arithmetic In Re-Allocated Memory?
    ... If your compiler ... it works with a cast. ... Pointer arithmetic, as you probably know, is scaled by ... not sure about concerning realloc(). ...
    (comp.lang.c)
  • Re: Problem with malloc
    ... In C you need not cast void pointers. ... void pointer to any other pointer type. ... >> If your compiler pukes at that then you need a new ...
    (comp.lang.c)
  • Re: Another ANSI C question about volatile
    ... > The cast is on the address of x. ... > lvalue of type 'pointer to volatile int'. ... > volatile, ... > that a compiler, needing to reread xp each time, would then ...
    (comp.lang.c)