H
harsh.murari
In the example below, a single object (Network) is implementing 2
interfaces (INetworkA and INetworkB). Both of these interfaces derive
from the IBase interface (similar to the IUnknown interface of the COM
world). Network object also implements the QueryInterface methods from
IBase interface.
In the main function, I am doing a QueryInterface on the INetworkA
interface. It returns me the pointer to the second interface
INetworkB. On this pointer, if I perform a function of the INetworkB,
the control is jumping into one of INetworkA's functions.
Can anyone tell me why this is happening? The problem goes away if I
am doing a cast when I am returning the interface pointer. But I am
still not convinced that this is the correct behavior by the compiler.
How does casting affect a V-table of a object pointer?
The below program compiles and runs fine on a GNU C++ compiler.
#include <stdio.h>
/* Base Interface */
class IBase
{
public:
virtual int F1() = 0;
virtual int QueryInterface (void **ppOut) = 0;
virtual int QueryInterface2 (void **ppOut) = 0;
};
/* Some interface */
class INetworkA: public IBase
{
public:
virtual int NA() = 0;
virtual int QueryInterface (void **ppOut) = 0;
};
/* Another interface */
class INetworkB: public IBase
{
public:
virtual int NB() = 0;
};
/* This object implements both interfaces */
class Network : public INetworkA,
public INetworkB
{
public:
int F1() { printf("Network::F1()\n"); }
int NA() { printf("Network::NA()\n"); }
int NB() { printf("Network::NB()\n"); }
int QueryInterface (void **ppOut) {*ppOut = this; return 0;}
int QueryInterface2 (void **ppOut) {*ppOut = (INetworkB *) this;
return 0;}
};
int main()
{
Network *netObj = new Network();
INetworkA *pINetA = netObj;
INetworkB *pINetB = netObj;
pINetA->NA();
pINetB->NB();
/* Weirdness happens here */
/* Get the INetworkB interface using QueryInterface() with no
casting */
pINetA->QueryInterface ((void **) &pINetB);
pINetB->NB();
/* Get the INetworkB interface using QueryInterface2() which does
casting*/
pINetA->QueryInterface2 ((void **) &pINetB);
pINetB->NB();
return 0;
}
interfaces (INetworkA and INetworkB). Both of these interfaces derive
from the IBase interface (similar to the IUnknown interface of the COM
world). Network object also implements the QueryInterface methods from
IBase interface.
In the main function, I am doing a QueryInterface on the INetworkA
interface. It returns me the pointer to the second interface
INetworkB. On this pointer, if I perform a function of the INetworkB,
the control is jumping into one of INetworkA's functions.
Can anyone tell me why this is happening? The problem goes away if I
am doing a cast when I am returning the interface pointer. But I am
still not convinced that this is the correct behavior by the compiler.
How does casting affect a V-table of a object pointer?
The below program compiles and runs fine on a GNU C++ compiler.
#include <stdio.h>
/* Base Interface */
class IBase
{
public:
virtual int F1() = 0;
virtual int QueryInterface (void **ppOut) = 0;
virtual int QueryInterface2 (void **ppOut) = 0;
};
/* Some interface */
class INetworkA: public IBase
{
public:
virtual int NA() = 0;
virtual int QueryInterface (void **ppOut) = 0;
};
/* Another interface */
class INetworkB: public IBase
{
public:
virtual int NB() = 0;
};
/* This object implements both interfaces */
class Network : public INetworkA,
public INetworkB
{
public:
int F1() { printf("Network::F1()\n"); }
int NA() { printf("Network::NA()\n"); }
int NB() { printf("Network::NB()\n"); }
int QueryInterface (void **ppOut) {*ppOut = this; return 0;}
int QueryInterface2 (void **ppOut) {*ppOut = (INetworkB *) this;
return 0;}
};
int main()
{
Network *netObj = new Network();
INetworkA *pINetA = netObj;
INetworkB *pINetB = netObj;
pINetA->NA();
pINetB->NB();
/* Weirdness happens here */
/* Get the INetworkB interface using QueryInterface() with no
casting */
pINetA->QueryInterface ((void **) &pINetB);
pINetB->NB();
/* Get the INetworkB interface using QueryInterface2() which does
casting*/
pINetA->QueryInterface2 ((void **) &pINetB);
pINetB->NB();
return 0;
}