Re: Casting of pointer to member functions
- From: "Alex Blekhman" <xfkt@xxxxxxxxx>
- Date: Mon, 18 Sep 2006 14:43:55 +0300
"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
.
- References:
- Casting of pointer to member functions
- From: David Olsson
- Re: Casting of pointer to member functions
- From: Alex Blekhman
- Re: Casting of pointer to member functions
- From: David Olsson
- Casting of pointer to member functions
- Prev by Date: Re: [newbie] new and delete
- Next by Date: Re: regarding Object Unwinding
- Previous by thread: Re: Casting of pointer to member functions
- Next by thread: Re: Casting of pointer to member functions
- Index(es):
Relevant Pages
|