QueryInterface 中的使用的类型转换,小弟我试了一下如何跟书上说的不一样
QueryInterface 中的使用的类型转换,我试了一下怎么跟书上说的不一样?
《atl 开发指南》一书中开头提到Math 类的例子,有段话这么说:“QueryInterface 检查客户是否请求一个支持的接口,并返回一个指向合适的 Vtable 指针的指针。请记住,在使用多继承的时候,你必须显式的转换实例的类型才能获得正确的Vtable。”
一个子类的指针,强制转换为父类指针的类型,就可以当父类来使用吗?当多个父类生成一个子类时,可以用这种方法指定转换为某一个父类,这么神奇?于是我想试验一下。
Math 类是由IMath(基本四则运算)与IAdvancedMath(高级数学运算)组成的,再加个IUnknown,3接口。
我现在用另外一个小程序,来模拟这个QueryInterface 中的强制类型转换。这个小程序并没有完全按照COM规范来,没有完全用纯虚函数,但是不影响实验,而且这样更能体现主旨。
先看看书上的源码:
再看看我要实验的小程序:
为什么是这样的 结果?为什么不是书上讲的那样?
------解决方案--------------------
楼主看看这个
------解决方案--------------------
virtual HRESULT getp(void *&p ){p = this; return 0;};
当你把类对象的指针赋给void *类型的数据时,会把类的信息都消除掉了。正确的做法是
《atl 开发指南》一书中开头提到Math 类的例子,有段话这么说:“QueryInterface 检查客户是否请求一个支持的接口,并返回一个指向合适的 Vtable 指针的指针。请记住,在使用多继承的时候,你必须显式的转换实例的类型才能获得正确的Vtable。”
一个子类的指针,强制转换为父类指针的类型,就可以当父类来使用吗?当多个父类生成一个子类时,可以用这种方法指定转换为某一个父类,这么神奇?于是我想试验一下。
Math 类是由IMath(基本四则运算)与IAdvancedMath(高级数学运算)组成的,再加个IUnknown,3接口。
我现在用另外一个小程序,来模拟这个QueryInterface 中的强制类型转换。这个小程序并没有完全按照COM规范来,没有完全用纯虚函数,但是不影响实验,而且这样更能体现主旨。
先看看书上的源码:
STDMETHODIMP Math::QueryInterface( REFIID riid, void** ppv )
{
*ppv = 0;
if ( riid == IID_IUnknown )
*ppv = (IMath*) this;
else if ( riid == IID_IMath )
*ppv = (IMath*) this;
else if ( riid == IID_IAdvancedMath )
*ppv = (IAdvancedMath*) this;
if ( *ppv )
{
AddRef();
return( S_OK );
}
return (E_NOINTERFACE);
}
再看看我要实验的小程序:
class IUk{ //相当于IUnknown
public:
virtual HRESULT getp(void *&p)=0;
};
class CA :public IUk{ //相当于书上的IMath
public:
virtual void fun(){cout<<"this is A::fun"<<endl;}
};
class CB:public IUk{ //相当于IAdvancedMath
public:
virtual void fun(){cout<<"this is CB::fun"<<endl;}
};
class CC:public CA,public CB{ //相当于MATH
public:
virtual HRESULT getp(void *&p ){p = this; return 0;};
};
int main()
{
void * p=0;
CC *p_c = new CC();
p_c->getp(p);
CB *p2 = (CB *)p; //转换为CB类指针
p2->fun(); //output: This is CA.
delete p_c;
system("pause");
return 0;
}
为什么是这样的 结果?为什么不是书上讲的那样?
------解决方案--------------------
楼主看看这个
#include "stdafx.h"
#include <iostream>
#include <objbase.h>
using namespace std;
class IUk{ //相当于IUnknown
public:
virtual HRESULT getp(void *&p)=0;
};
class CA :public IUk{ //相当于书上的IMatha
public:
virtual void fun(){cout<<"this is A::fun"<<endl;}
};
class CB:public IUk{ //相当于IAdvancedMath
public:
virtual void fun(){cout<<"this is CB::fun"<<endl;}
};
class CC:public CA,public CB{ //相当于MATH
public:
virtual HRESULT getp(void *&p ){
p = this;
return 0;
};
};
int main()
{
void * p=0;
CC *p_c = new CC();
//p_c->getp(p);
//CB *p2 = static_cast<CB *>(p); //转换为CB类指针
//p2->fun(); //output: This is CA.
CB* pb = NULL;
pb = static_cast<CB*> (p_c);
pb->fun();
delete p_c;
system("pause");
return 0;
}
------解决方案--------------------
virtual HRESULT getp(void *&p ){p = this; return 0;};
当你把类对象的指针赋给void *类型的数据时,会把类的信息都消除掉了。正确的做法是
class IUk{ //相当于IUnknown
public:
virtual int getp(void **p)=0;
};
class CA :public IUk{ //相当于书上的IMath
public:
virtual void fun(){cout<<"this is A::fun"<<endl;}
};
class CB:public IUk{ //相当于IAdvancedMath
public:
virtual void fun(){cout<<"this is CB::fun"<<endl;}
};
class CC:public CA,public CB{ //相当于MATH
public:
virtual int getp(void **p){*p = this; return 0;};
};
int main()
{
CC * p=0;
CC *p_c = new CC();