On Saturday, 25 July 2015 at 09:44:30 UTC, Jacob Carlborg wrote:
On 2015-07-24 21:04, Walter Bright wrote:

Dynamic cast is no different from QueryInterface(), which is how it's done, and the reason is the point of all this - avoiding needing to enumerate every interface needed by the leaves at the root of the call
tree.

I'm not familiar with QueryInterface():

It's part of COM. Basically, it's equivalent to doing something like

auto f = cast(MyInterface)myObj;
if(f is null)
{ /+ you can't convert it to MyInterface +/ }
else
{ /+ you _can_ convert it +/ }

except that with the way that QueryInterface works, it's actually possible to get a completely different object out of it. It doesn't have to have any relation to the original object, and the new type doesn't have to be in an inheritance hierarchy with the original type. So, you can do wacky stuff like have an interface which relates to one object hierarchy and convert it to an interface from a completely unrelated object hierarchy just so long as the underlying type knows how to give you the type you're asking for (be it because it implements both interfaces or because it's designed to give you an object that implements the interface you're asking for).

So, QueryInterface isn't actually guaranteed to do anything like a cast at all. It just guarantees that you'll either get an object of the type you ask for - somehow - or that the call will fail.

And the way it's used often seems to be the equivalent of something like

interface A {}
interface A : B {}

interface Foo {}
interface Bar : Foo {}

class MyClass : B, Bar {}

Foo f = getFoo(); // returns what it is actually a MyClass
A a = cast(A)f;

It happens to work, because the underlying type implements both, but why on earth would you expect that a Foo would be related to an A when they're completely unrelated? And yet that seems to be the sort of thing that gets done with QueryInterface - at least in the code that I've worked with that does COM.

Personally, I think that it's nuts to even be attempting to cast from one interface to an entirely unrelated one and expect it to work - or to write code in a way that that's a normal way to do things.

- Jonathan M Davis

Reply via email to