I'm working on retrieving some info from windows task scheduler. MSDN indicates there are several types of action. I want to deal with them separately. I tried:
IAction* pAction = NULL;
pActionCollection->get_Item(_variant_t(i), &pAction);
if (IExecAction* pExecAction = dynamic_cast<IExecAction*>(pAction)) { /*my work...*/ }
if (IComHandlerAction* pComHandlerAction = dynamic_cast<IComHandlerAction*>(pAction)) { /*my work...*/ }
if (IEmailAction* pEmailAction = dynamic_cast<IEmailAction*>(pAction)) { /*my work...*/ }
if (IShowMessageAction* pShowMessageAction = dynamic_cast<IShowMessageAction*>(pAction)) { /*my work...*/ }
But this program throws exception at the first dynamic_cast
.
Exception thrown at 0x00007FFB516365A5 (vcruntime140d.dll) in myProgram.exe: 0xC0000005: Access violation reading location 0x00000130BAFEDB04.
The definition in taskschd.h
shows IExecAction
is a derived class from IAction
.
This works well:
if (IExecAction* pExecAction = ((IExecAction*)pAction)) { /*my work...*/ }
But what if I want to do some type checking? How could I use it properly?
for get pointer of com interface from another com interface on the same object we need use only
QueryInterface
method, which is always implemented by any interface. so code in your case need to be next:even if one interface inherit from another use c/c++ cast is always wrong. for example
this code is correct from c++ syntax, because both
IExecAction : IAction
andIEmailAction : IAction
inherit fromIAction
. and this cast (if take to account layout of this 3 interfaces) give you equal binary values forpExecAction
andpEmailAction
. butpExecAction
can not have the same binary value aspEmailAction
. must bewhy ? because have
pEmailAction
andpExecAction
have different virtual functions at the same position in vtable. for example on the 10-th position in the table ofIExecAction
must be pointer toget_Path
method. from another side on the 10-th position in the table ofIEmailAction
must be pointer toget_Server
method. if(void*)pEmailAction == (void*)pExecAction
- they will be have the same pointers to vtable. but pointer to which function -get_Path
orget_Server
will be in the 10-th position ? as result pointer to this 2 interfaces can not be the same (point to the same memory). so how minimum onestatic_cast
here (may be and both) give wrong result. for understand howQueryInterface
work and why pointers topExecAction
andpEmailAction
wiil be different - we need look for implementation. implementation of interfaces - this is some class, which inherit (usually) from all this interfaces and implement it like this:look that
static_cast<IExecAction*>(this);
will always give another binary value comparestatic_cast<IEmailAction*>(this);
- theCAction
will be containing 2 different vtables - one forIExecAction
and one forIEmailAction
. they have common initial part (9 entries) but then different. andstatic_cast<IExecAction*>(this);
andstatic_cast<IEmailAction*>(this);
return 2 different (always) pointers to this 2 different vtables. when forIAction*
we select return or first or second vtable pointer. both will be correct. what pointer return implementation - we can not know (the layout of actual class which implementIExecAction
,IEmailAction
is unknown for us)