Casting pointers
Frits van Bommel
fvbommel at REMwOVExCAPSs.nl
Sat Jul 7 08:00:38 PDT 2007
Henning Hasemann wrote:
> I have the following code:
>
> import std.stdio;
>
> interface I { void foo(); }
>
> class C : I {
> void foo() { writefln("foo called"); }
> }
>
> void main() {
> auto c = new C;
> I* i = cast(I*)(&c);
> (*i).foo();
> }
>
> What I'd expect it to do would be to write "foo called".
> Instead it prints out "icast.C" with dmd-1.018.
>
> Did I something wrong casting the address of c (which is in fact a
> reference to a reference)? If so shouldnt there be a compiler error?
Yes, you did something wrong. You cast a pointer to an object reference
to a pointer to an interface reference and expected it to do something
meaningful. Interfaces use different vtables than objects, so the binary
representation of the references won't be the same even if they
reference the same actual object. (Interface pointers point to the
address of the interface vtable pointer in the object instead of to the
start of the object (where the class vtable is)).
(What's happening in your program: I.foo() probably occupies the same
position in the interface vtable as Object.print() does in the class
vtable. Since you haven't overridden toString() that then prints the
name of the class; I guess your source file is named icast.d?)
I don't think this should be a compile error since pointer casting is
technically allowed, but an optional warning might be nice. However,
pointer-casting is generally a bad idea so the best solution is just to
avoid it as much as possible.
> Is there any way to have the address of the Variable c interpreted as
> an address to a I-interface at all? I know it works without the address
> stuff but I'd really like to use this pointer-to-reference semantic.
First cast to a C* (or Object*), then dereference it and cast to I.
These'll probably work:
---
I i = cast(I) *cast(Object*) &c;
// and
I i = cast(I) *cast(C*) &c;
// though cast(C*) is pretty useless here :)
---
(You can't get a pointer to an interface this way unless you store the
result of "cast(I) ..." first, since there's no interface reference to
point to)
By the way, you shouldn't need to use "(*i).whatever"; pointers are
dereferenced automatically when members are accessed (except when you
need things like (*i).sizeof because those are also valid properties of
the pointers themselves).
More information about the Digitalmars-d
mailing list