IsKindOf()函数

8 篇文章 0 订阅
原文链接:

知道有IsKindOf这么个函数,用来检测:(1)对象是否属于指定的类,(2)对象是否属于指定类派生的类,但是一直没用过,今天用了下,提示错误errorC2039: 'classXXX' : is not a member of'XXX',查了很多资料,才把它搞明白,记录如下:

1、对使用IsKindOf这个函数的类要在.h文件夹里定义DECLARE_DYNAMIC或DECLARE_SERIAL宏
class CDlgTest : public CDialog
{
DECLARE_DYNAMIC( CDlgTest )
// Construction
public:
CDlgTest(CWnd* pParent = NULL);   // standardconstructor
...
...
};
2、需要在.cpp文件中加入IMPLEMENT_DYNAMIC或IMPLEMENT_SERIAL宏
[cpp] view plaincopy
IMPLEMENT_DYNAMIC(CDlgTest, CDialog)  
   
CDlgTest::CDlgTest(CWnd* pParent )  
    : CDialog(CDlgTest::IDD,pParent)  
{  
    ... 
}  

3、使用时,CDlgTest dlg;

                  if(dlg.IsKinfOf(CDialog))...

 

随后又研究了一下这几个宏,也算明白了IsKindOf的实现原理,做下简单记录:

1、DECLARE_DYNAMIC宏

[cpp] view plaincopy
#define DECLARE_DYNAMIC(class_name)/      
public:/  
    static CRuntimeClassclass##class_name;/        
      virtual CRuntimeClass* GetRuntimeClass() const; 

2、IMPLEMENT_DYNAMIC宏

[cpp] view plaincopy
#define IMPLEMENT_DYNAMIC(class_name,bass_class_name)/ 
        _IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,0xFFFF,NULL) 
   
#define_IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,wSchema,pfnNew)/ 
    static char_lpsz##class_name[]= #class_name;/  
    CRuntimeClassclass_name::class##class_name = {/  
        _lpsz##class_name,sizeof(class_name),wSchema,pfnNew,/ 
            RUNTIME_CLASS(base_class_name),NULL};/  
    static AFX_CLASSINIT_init_##class_name(&class_name::class##class_name);/ 
    CRuntimeClass*class_name::GetRuntimeClass() const/  
        { return&class_name::class##class_name;} 

3、IsKindOf函数的实现

// example forCObject::GetRuntimeClass
CAge a(21);
CRuntimeClass* prt =a.GetRuntimeClass();
ASSERT( strcmp(prt->m_lpszClassName, "CAge" )   ==0 );

Return Value:
A pointer to the CRuntimeClassstructure corresponding to this object's class; never NULL.

[cpp] view plaincopy
BOOL  CRuntimeClass::IsDerivedFrom(const CRuntimeClass*pClass) const      
{      
    CRuntimeClass*pClassThis=this;      
    while(pClassThis !=NULL)      
    {      
        if(pClassThis==pClass)      
            returnTRUE;      
        pClassThis=pClassThis->m_pBaseClass;     
    }      
    return FALSE;     
}      

BOOL CObject::IsKindOf(const CRuntimeClass* pClass)const
{
ASSERT(this != NULL);
// it better be in valid memory, at least for CObjectsize
ASSERT(AfxIsValidAddress(this, sizeof(CObject)));

// simple SI case
CRuntimeClass* pClassThis = GetRuntimeClass();
return pClassThis->IsDerivedFrom(pClass);
}

4、单行宏的定义

定义单行宏:主要有以下三种用法.

1) 前加##或后加##,将标记作为一个合法的标识符的一部分.注意,不是字符串.多用于多行的宏定义中.例如:
    #define A(x)  T_##x
    则 int A(1) = 10;//等效于int T_1 = 10;
    #define A(x)  Tx##__
    则 int A(1) = 10;//等效于int T1__ = 10;
2) 前加#@,将标记转换为相应的字符,注意:仅对单一标记转换有效
      #define B(x) #@x
      则B(a)即'a',B(1)即 '1'.但B(abc)却不甚有效.
3) 前加#,将标记转换为字符串.
      #define C(x) #x
      则C(1+1) 即 "1+1".


其余网上搜索:

主要检查一下对象否从某一类类派生,但此类必须从CObject派生(或间接),并且使用DECLARE_DYNAMIC/DECLARE_SEARIAL等宏

比如我们函数的参数是个基类的指针类型。那么当我外部传过来一个子类的指针时,在函数内部就可以用这种语句来确认传进来的是这个子类的对象,而不是其它子类的对象

ASSERT(xxx->IsKinfOf(RUNTIME_CLASS(yyy)) 判断xxx所指的类是否为yyy的子类!

指针的类型和指针指向的对象的类型可以是不一样的,这就是指针的灵活性;但是这种灵活性是不安全的,因为可以随意转换,所以前面用一个ASSERT判断一下。

其实现在在C++中也可以使用安全的类型转换:static_cast、dynamic_cast等。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值