Downcasting interface references
Asked Answered
P

1

7

I'm getting a run-time exception when I try to cast an object to an interface that I'm pretty sure it implements.

I have the following interfaces:

public interface class ISMILTimeContainer;
public interface class ISMILSequence : ISMILTimeContainer;
public interface class ISMILParallel : ISMILTimeContainer;

I have the following classes:

ref class TimeContainer : public ISMILTimeContainer;
ref class Sequence : public TimeContainer, ISMILSequence;
ref class Parallel : public TimeContainer, ISMILParallel;

Then, I try the following:

ISMILTimeContainer^ container = getSequence(); // returns a Sequence^
ISMILSequence^ sequence = static_cast<ISMILSequence^>(container);

This throws an exception at run-time:

Platform::InvalidCastException ^ at memory location 0x04AFD83C. HRESULT:0x80004002 No such interface supported

As far as I can tell, this should be working. Is there something wrong with what I'm trying to do, or do the symptoms indicate an implementation issue (something is different than what is claimed above)?

Pericynthion answered 4/11, 2014 at 18:25 Comment(2)
Can you show getSequence? I tried to repro your code and do not get an exception. For me it works. All I changed was the line that calls getSequence to this: ISMILTimeContainer^ container = ref new Sequence(); Perhaps getSequence doesn't return a Sequence?Cinchonidine
There is no such thing as inheriting a class in WinRT. It's internally done using composition. I think in this case you could use safe_cast, which should work "across" and not just up and down. Think of it as a pathfinding cast I guess.Finegrain
B
3

Your container is an ISMILTimeContainer created by implicit cast. This is upcasting, casting a derived class object (the return value of getSequence(), a Sequence) to a parent or base class object (the ISMILTimeContainer).

When you then try to downcast to an ISMILSequence in your next statement, because you have an inheritance chain, you pass compiler checks using static_cast<ISMILSequence^>.

However, C++/CX also runs runtime checks [1], and in this case it seems that your container variable, of type ISMILTimeContainer, does not have all of the information required to form an ISMILSequence in your second statement. Although an ISMILSequence IS-A ISMILTimeContainer, the opposite is not true.

For information about up-casting and down-casting, see [2] or other google results. The later sections in this blog post might be of help.

Brimstone answered 7/11, 2014 at 0:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.