The usage of RTTI in C++

  • 2020-05-27 06:47:28
  • OfStack

The usage of RTTI in C++

RTTI is short for run-time type recognition (Runtime Type Identification). This is one of the new features added to c++, which many older implementations do not support. Other implementations may include compiler Settings for the switch RTTI. RTTI is designed to provide a standard way for programs to determine object types at run time. Many libraries have become superclass objects that provide the ability to do this. However, since c++ is not supported internally, vendor mechanisms are often incompatible. Creating an RTTI language standard will make future libraries compatible with each other.

c++ has three elements that support RTTI

If possible, the dynamic_cast operator will use a pointer to a base class to generate a pointer to a derived class. Otherwise, the operator returns 0 -- a null pointer

The typied operator returns a value indicating the type of the object

The type_info structure stores information about a particular type

Suppose we have the following class hierarchy:


class Grand{ //has virtual methods};
class Super:public Grand {...}
class Magnificent : public Superb{...}

Suppose you have the following pointer:


Grand *pg = new Grand ;
Grand *ps = new Superd;
Grand *pm = new Manificent;

1, dynamic_cast

Let's take a look at the syntax for dynamic_cast for 1. The syntax is used as follows, where pg points to an object


Superb pm = dynamic_cast< Superb > (pg) ; 

This pointer pg returns the object address if it can be safely converted to Superb *, otherwise it returns a null pointer.

Example:


// test1002.cpp :  Define the entry point for the console application. 
//

#include "stdafx.h"
#include <cstdlib>
#include <ctime>
#include<iostream>

using std::cout;
class Grand
{
private:
  int hold;
public :
  Grand(int h = 0) :hold(h) {}
  virtual void Speak() const { cout << "I am a grand class \n"; }
  virtual int Value() const { return hold; }
};

class Superb :public Grand
{
public :
  Superb(int h = 0) :Grand(h) {}
  void Speak() const { cout << "I am a superb class ! \n"; }
  virtual void Say() const 
  {
    cout << "I hold the superb value of " << Value() << "! \n";
  }
};

class Magnificent : public Superb
{
private :
  char ch;
public :
  Magnificent(int h = 0, char c = 'A') :Superb(h), ch(c)
  {
  }
  void Speak() const 
  {
    cout << "I am a magnificent class !!!! \n";
  }
  void Say() const
  {
    cout << "I hold the character " << ch << " and the integer " << Value() <<"! \n";
  }
};

Grand * GetOne();
int main()
{
  std::srand(static_cast<unsigned int>(std::time(0)));
  Grand * pg;
  Superb * ps;
  for (int i = 0; i < 5; i++)
  {
    pg = GetOne();
    pg->Speak();
    if (ps = dynamic_cast<Superb *>(pg)) {
      ps->Say();
    }
  }
  system("pause");
  return 0;
}
Grand * GetOne()
{
  Grand * p = new Grand();
  switch (std::rand() % 3)
  {
    delete p;
  case 0:p = new Grand(std::rand() % 100); break;
  case 1:p = new Superb(std::rand() % 100); break;
  case 2:p = new Magnificent(std::rand() % 100, std::rand() % 26); break;
  }

  return p;
}
 The results :
I am a superb class !
I hold the superb value of 3!
I am a magnificent class !!!!
I hold the character  and the integer 5!
I am a grand class
I am a grand class
I am a magnificent class !!!!
I hold the character  and the integer 87!
 Please press any key to continue . . .

2. typied operation conforms to type_info class

The typied operator can determine whether two objects are of the same type. It takes two arguments: 1, the name of the class, 2, and the result is an expression for the object

The typied operator returns a reference to an type_info object, type_info defined in the header file typeinfo(previously typeinfo.h). The type_info class is overloaded with == and! = operator so that you can use these operators to compare types.

Example: typeid(Manificnent) == typeid(*pg) this expression results in an bool value

If pg is a null pointer, the program throws an bad_typied exception. This exception type is derived from the exception class. It's declared in typeinfo.

The implementation of the type_info class varies from vendor to vendor, but contains one name() member, which returns a string that varies with the implementation: usually the name of the class.

The sample


// test1002.cpp :  Define the entry point for the console application. 
//

#include "stdafx.h"
#include <cstdlib>
#include <ctime>
#include<iostream>
#include <typeinfo>
using std::cout;
class Grand
{
private:
  int hold;
public :
  Grand(int h = 0) :hold(h) {}
  virtual void Speak() const { cout << "I am a grand class \n"; }
  virtual int Value() const { return hold; }
};

class Superb :public Grand
{
public :
  Superb(int h = 0) :Grand(h) {}
  void Speak() const { cout << "I am a superb class ! \n"; }
  virtual void Say() const 
  {
    cout << "I hold the superb value of " << Value() << "! \n";
  }
};

class Magnificent : public Superb
{
private :
  char ch;
public :
  Magnificent(int h = 0, char c = 'A') :Superb(h), ch(c)
  {
  }
  void Speak() const 
  {
    cout << "I am a magnificent class !!!! \n";
  }
  void Say() const
  {
    cout << "I hold the character " << ch << " and the integer " << Value() <<"! \n";
  }
};

Grand * GetOne();
int main()
{
  std::srand(static_cast<unsigned int>(std::time(0)));
  Grand * pg;
  Superb * ps;
  for (int i = 0; i < 5; i++)
  {
    pg = GetOne();
    cout << "Now Process type " << typeid (*pg).name() << ". \n"; // According to 
    pg->Speak();
    if (ps = dynamic_cast<Superb *>(pg)) {
      ps->Say();
    }
  }
  system("pause");
  return 0;
}
Grand * GetOne()
{
  Grand * p = new Grand();
  switch (std::rand() % 3)
  {
    delete p;
  case 0:p = new Grand(std::rand() % 100); break;
  case 1:p = new Superb(std::rand() % 100); break;
  case 2:p = new Magnificent(std::rand() % 100, std::rand() % 26); break;
  }

  return p;
}
 The results :
Now Process type class Superb.
I am a superb class !
I hold the superb value of 86!
Now Process type class Grand.
I am a grand class
Now Process type class Superb.
I am a superb class !
I hold the superb value of 48!
Now Process type class Grand.
I am a grand class
Now Process type class Magnificent.
I am a magnificent class !!!!
I hold the character and the integer 75!
 Please press any key to continue . . .

The above code adds a sentence typied(*pg).name() is used to output type information. The output is usually the class name.

If you have any questions, please leave a message or come to the site community to exchange discussion, thank you for reading, hope to help you, thank you for your support of the site!


Related articles: