Kernel SDK Developer's Guide > Run-Time Type Identification > Example of Belonging to an Instance to a Class
Example of Belonging to an Instance to a Class

To check whether an instance belongs to or is derived from a specified class, use the following methods of the OdRxObject class:

  • isKindOf() method — Returns true when the instance belongs to the specified class or false otherwise.
  • queryX() — Returns an address of the instance when it belongs to the specified class, or NULL otherwise.
  • x() — Returns an address of the instance when it belongs to the specified class, or generates the eNotThatKindOfClass exception otherwise.

These methods require a raw pointer to the class describing instance as an argument.

For example, consider the following hierarchy of classes: the AObj class is directly derived from the OdRxObject class; the BObj class and DObj class are derived from the AObj class; the CObj class is derived from the BObj class; the EObj class and FObj class are derived from the DObj class; the BObj, CObj classes are one branch of the tree; the DObj, EObj, FObj classes are other branch of the tree.

To declare the standard RTTI methods, use the ODRX_DECLARE_MEMBERS macro. The listed classes have the following definition:

class AObj : public OdRxObjectImpl<OdRxObject>
{
 public:
   ODRX_DECLARE_MEMBERS(AObj);
 public:
   AObj();
   ~AObj();
};

typedef OdSmartPtr<AObj> AObjPtr;

class BObj : public AObj
{
 public:
   ODRX_DECLARE_MEMBERS(BObj);
 public:
   BObj();
   ~BObj();
};

typedef OdSmartPtr<BObj> BObjPtr;

class CObj : public BObj
{
 public:
   ODRX_DECLARE_MEMBERS(CObj);
 public:
   CObj();
   ~CObj();
};

typedef OdSmartPtr<CObj> CObjPtr;

class DObj : public AObj
{
 public:
   ODRX_DECLARE_MEMBERS(DObj);
 public:
   DObj();
   ~DObj();
};

typedef OdSmartPtr<DObj> DObjPtr;

class EObj : public DObj
{
 public:
   ODRX_DECLARE_MEMBERS(EObj);
 public:
   EObj();
   ~EObj();
};

typedef OdSmartPtr<EObj> EObjPtr;

class FObj : public DObj
{
 public:
   ODRX_DECLARE_MEMBERS(FObj);
 public:
   FObj();
   ~FObj();
};

typedef OdSmartPtr<FObj> FObjPtr;

To implement the standard RTTI methods, use the ODRX_CONS_DEFINE_MEMBERS macro. When you specify the class names in this macro, you must keep the hierarchical order of inheritance. Methods of these classes have the following implementation:

ODRX_CONS_DEFINE_MEMBERS(AObj, OdRxObject, NEWOBJ_CONSTR);

AObj::AObj()  {}
AObj::~AObj() {}

ODRX_CONS_DEFINE_MEMBERS(BObj, AObj, NEWOBJ_CONSTR);

BObj::BObj()  {}
BObj::~BObj() {}

ODRX_CONS_DEFINE_MEMBERS(CObj, BObj, NEWOBJ_CONSTR);

CObj::CObj()  {}
CObj::~CObj() {}

ODRX_CONS_DEFINE_MEMBERS(DObj, AObj, NEWOBJ_CONSTR);

DObj::DObj()  {}
DObj::~DObj() {}

ODRX_CONS_DEFINE_MEMBERS(EObj, DObj, NEWOBJ_CONSTR);

EObj::EObj()  {}
EObj::~EObj() {}

ODRX_CONS_DEFINE_MEMBERS(FObj, DObj, NEWOBJ_CONSTR);

FObj::FObj()  {}
FObj::~FObj() {}

For testing these classes, the example creates an array of instances that will belong to other classes. To print information about the class hierarchy for each pair of instances of this array, the example implements the TestKindOf() function that uses the isKindOf() method, the TestQueryX() function that uses the queryX() method, and the TestX() function that uses the x() method. The PrintClassNames() function prints the class names and addresses of instances in the array. The Main module has the following implementation:

#include "OdaCommon.h"
#include "OdToolKit.h"
#include "..\..\Teigha.dwg\Extensions\ExServices\ExHostAppServices.h"
#include "..\..\Teigha.dwg\Extensions\ExServices\ExSystemServices.h"

class MyApp : public ExSystemServices 
{
 protected:
   ODRX_USING_HEAP_OPERATORS(ExSystemServices);
 public:
   MyApp() {};
};

void PrintClassNames(OdRxObjectPtr pArr[], int count)
{
  for(int i=0 ; i < count ; i++)
    odPrintConsoleString(L"\nclass %s \tInstance %x", pArr[i]->isA()->name().c_str(), pArr[i]); 
}

void TestKindOf(OdRxObjectPtr pArr[], int count)
{
  for(int i=1 ; i < count ; i++)
    for(int j=0 ; j < count ; j++)
      if(i != j)
        odPrintConsoleString(L"\nIs (%s) KindOf (%s) => %s", pArr[i]->isA()->name().c_str(),  
          pArr[j]->isA()->name().c_str(), (pArr[i]->isKindOf(pArr[j]->isA())) ? L"true" : L"false");
}

void TestQueryX(OdRxObjectPtr pArr[], int count)
{
  for(int i=1 ; i < count ; i++)
    for(int j=0 ; j < count ; j++)
      if(i != j)
        odPrintConsoleString(L"\nQuery (%s) --> (%s) => %x", pArr[i]->isA()->name().c_str(),  
          pArr[j]->isA()->name().c_str(), pArr[i]->queryX(pArr[j]->isA()));
}

void TestX(OdRxObjectPtr pArr[], int count)
{
  for(int i=1 ; i < count ; i++)
    for(int j=0 ; j < count ; j++)
      if(i != j)
        try 
        {
          odPrintConsoleString(L"\nQuery (%s) --> (%s) => ", pArr[i]->isA()->name().c_str(), pArr[j]->isA()->name().c_str());
          odPrintConsoleString(L"%x", pArr[i]->x(pArr[j]->isA()));
        }
        catch(OdError_NotThatKindOfClass err)
        {
          odPrintConsoleString(L"\nExcept %d - %s (KindOf)", err.code(), err.description().c_str());
        }
  try 
  {
    odPrintConsoleString(L"\n%x", pArr[0]->x(NULL));
  }
  catch(OdError e)
  {
    odPrintConsoleString(L"\nExcept %d - %s ", e.code(), e.description().c_str());
  }
}

#include <conio.h>

int main()
{
  OdStaticRxObject<MyApp> svcs;

  odInitialize(&svcs);
  AObj::rxInit();
  BObj::rxInit();
  CObj::rxInit();
  DObj::rxInit();
  EObj::rxInit();
  FObj::rxInit();

  OdRxObjectPtr pArr[6];
  pArr[0] = AObj::createObject();
  pArr[1] = BObj::createObject();
  pArr[2] = CObj::createObject();
  pArr[3] = DObj::createObject();
  pArr[4] = EObj::createObject();
  pArr[5] = FObj::createObject();

  PrintClassNames(pArr, 6);
  getch();

  TestKindOf(pArr, 6);
  getch();

  TestQueryX(pArr, 6);
  getch();

  TestX(pArr, 6);
  getch();

  FObj::rxUninit();
  EObj::rxUninit();
  DObj::rxUninit();
  CObj::rxUninit();
  BObj::rxUninit();
  AObj::rxUninit();
  odUninitialize();

  return 0;
}

The PrintClassNames() function prints the following result:

class AObj      Instance 135a510
class BObj      Instance 135a528
class CObj      Instance 135a540
class DObj      Instance 135a558
class EObj      Instance 135a570
class FObj      Instance 135a588

The TestKindOf() function prints the following result:

Is (BObj) KindOf (AObj) => true
Is (BObj) KindOf (CObj) => false
Is (BObj) KindOf (DObj) => false
Is (BObj) KindOf (EObj) => false
Is (BObj) KindOf (FObj) => false
Is (CObj) KindOf (AObj) => true
Is (CObj) KindOf (BObj) => true
Is (CObj) KindOf (DObj) => false
Is (CObj) KindOf (EObj) => false
Is (CObj) KindOf (FObj) => false
Is (DObj) KindOf (AObj) => true
Is (DObj) KindOf (BObj) => false
Is (DObj) KindOf (CObj) => false
Is (DObj) KindOf (EObj) => false
Is (DObj) KindOf (FObj) => false
Is (EObj) KindOf (AObj) => true
Is (EObj) KindOf (BObj) => false
Is (EObj) KindOf (CObj) => false
Is (EObj) KindOf (DObj) => true
Is (EObj) KindOf (FObj) => false
Is (FObj) KindOf (AObj) => true
Is (FObj) KindOf (BObj) => false
Is (FObj) KindOf (CObj) => false
Is (FObj) KindOf (DObj) => true
Is (FObj) KindOf (EObj) => false

The TestQueryX() function prints the following result:

Query (BObj) --> (AObj) => 135a528
Query (BObj) --> (CObj) => 0
Query (BObj) --> (DObj) => 0
Query (BObj) --> (EObj) => 0
Query (BObj) --> (FObj) => 0
Query (CObj) --> (AObj) => 135a540
Query (CObj) --> (BObj) => 135a540
Query (CObj) --> (DObj) => 0
Query (CObj) --> (EObj) => 0
Query (CObj) --> (FObj) => 0
Query (DObj) --> (AObj) => 135a558
Query (DObj) --> (BObj) => 0
Query (DObj) --> (CObj) => 0
Query (DObj) --> (EObj) => 0
Query (DObj) --> (FObj) => 0
Query (EObj) --> (AObj) => 135a570
Query (EObj) --> (BObj) => 0
Query (EObj) --> (CObj) => 0
Query (EObj) --> (DObj) => 135a570
Query (EObj) --> (FObj) => 0
Query (FObj) --> (AObj) => 135a588
Query (FObj) --> (BObj) => 0
Query (FObj) --> (CObj) => 0
Query (FObj) --> (DObj) => 135a588
Query (FObj) --> (EObj) => 0

The TestX() function prints the following result:

Except 63 - Object of class BObj can't be cast to CObj. (KindOf)
Query (BObj) --> (DObj) =>
Except 63 - Object of class BObj can't be cast to DObj. (KindOf)
Query (BObj) --> (EObj) =>
Except 63 - Object of class BObj can't be cast to EObj. (KindOf)
Query (BObj) --> (FObj) =>
Except 63 - Object of class BObj can't be cast to FObj. (KindOf)
Query (CObj) --> (AObj) => 135a540
Query (CObj) --> (BObj) => 135a540
Query (CObj) --> (DObj) =>
Except 63 - Object of class CObj can't be cast to DObj. (KindOf)
Query (CObj) --> (EObj) =>
Except 63 - Object of class CObj can't be cast to EObj. (KindOf)
Query (CObj) --> (FObj) =>
Except 63 - Object of class CObj can't be cast to FObj. (KindOf)
Query (DObj) --> (AObj) => 135a558
Query (DObj) --> (BObj) =>
Except 63 - Object of class DObj can't be cast to BObj. (KindOf)
Query (DObj) --> (CObj) =>
Except 63 - Object of class DObj can't be cast to CObj. (KindOf)
Query (DObj) --> (EObj) =>
Except 63 - Object of class DObj can't be cast to EObj. (KindOf)
Query (DObj) --> (FObj) =>
Except 63 - Object of class DObj can't be cast to FObj. (KindOf)
Query (EObj) --> (AObj) => 135a570
Query (EObj) --> (BObj) =>
Except 63 - Object of class EObj can't be cast to BObj. (KindOf)
Query (EObj) --> (CObj) =>
Except 63 - Object of class EObj can't be cast to CObj. (KindOf)
Query (EObj) --> (DObj) => 135a570
Query (EObj) --> (FObj) =>
Except 63 - Object of class EObj can't be cast to FObj. (KindOf)
Query (FObj) --> (AObj) => 135a588
Query (FObj) --> (BObj) =>
Except 63 - Object of class FObj can't be cast to BObj. (KindOf)
Query (FObj) --> (CObj) =>
Except 63 - Object of class FObj can't be cast to CObj. (KindOf)
Query (FObj) --> (DObj) => 135a588
Query (FObj) --> (EObj) =>
Except 63 - Object of class FObj can't be cast to EObj. (KindOf)

Except 5 - Invalid input

See Also

RTTI Technology

Implementing RTTI Methods for the Derived Class

Belonging to an Instance of a Class

Copyright © 2002 – 2020. Open Design Alliance. All rights reserved.