how to check the type of a pointer in C++

12,748

Compile time differenciation:

You can use a template and its specialisation:

template <class T>
bool isName(T *t) { return false;  } // normal case returns false 
 
template <>
bool isName(Name *t) { return true; }  // but for Name returns true

Then you can differentiate your code, for example:

Name *n; Name1 *n1;
cout << "(1): " << isName(n) << endl;
cout << "(2): " << isName(n1) << endl;

You can of course use isName() in conditions to process depending on the class of the object.

From a design perspective, if you have class specific code, it may however be more interesting to wrap it in some templates, and use the specialisation demonstrated above, not for returning a boolean, but doing what is to be done, for example:

template <class T>
void doMyStuff(T *t) { }  // in general do nothing 
 
template <>
void doMyStuff(Name *t) { cout << "do something with Name*"<<endl; }

template <> 
void doMyStuff(Name1 *t) { cout << "do something with Name1*"<<endl; }

...
doMyStuff(n);
doMyStuff(n1);

Run time differentiation:

If you need to decide run time on an arbitrary pointer, you need dynamic run-time type information. The stantard C++ has RTTI for that. But it requires at least one virtual function in the class. So you can't just take any pointer (e.g. void*) and find out what data it points to ! You need a pointer to a valid polymorphic class.

The clean way to do it, would be to make Name and Name1 both inherit from a technical common class with a virtual function:

class vvoid {
    virtual void mv() {};
};

Then you can use dynamic_cast and the <typeinfo> to work with the type of your object, and use easily pointers to the base object :

void f(vvoid *p){
    cout<<"f("<<p<<"):"<<typeid(*p).name()<< endl;
}

You can then call this function by providing it a pointer to the derived classes:

Name *n=new Name;
Name1 *n1=new Name1;
f(n);   // no risk here, it's automatic conversion to base type 
f(n1); 

Note that for a better design you can also embedd any class specific behaviour in a virtual function, that is specialized for each derived type. But then it's the start of a solid class design, and your assumption was: unrelated classes.

A more error prone approach is to keep each of these classes independent but making sure that each has at least one virtual function, in order to ensure that they are polymorphic and contain RTTI information.

You could then use the dangerous reinterpret_cast and use access to RTTI information. This code demonstrate the principle:

f(reinterpret_cast<vvoid*>(n)); 
f(reinterpret_cast<vvoid*>(n1));
 

It seems to work. However, if by accident you'd cast a class that has no virtual function, your code would compile withour warnings but it would awfully stumble at execution.

Share:
12,748
ratzip
Author by

ratzip

Updated on June 27, 2022

Comments

  • ratzip
    ratzip almost 2 years

    I have the following code:

    // Example program
    #include <iostream>
    #include <string>
    #include <typeinfo>
    
    using namespace std;
    
    class Name
    {
        int a;
        int b;
    };
    
    class Name1
    {
        int a;
        int b;
    };
    
    
    int main()
    {
    
      Name1* name1;
      Name*  name;
    
      // trying to implement the following code:
      // check if name1 is of type of pointer Name1 then do someting
      // check if name is of type of pointer Name then do someting
    
    }
    

    how to check the type of pointer name1?

    Name1 and Name are not inherited, the dynamic_cast can not be used, then how to check the type of a pointer?