如何在C++中检查指针的类型

rat*_*zip 3 c++ types pointers

我有以下代码:

// 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

}
Run Code Online (Sandbox Code Playgroud)

如何检查指针的类型name1

Name1 和 Name 不是继承的,dynamic_cast 不能用,那么如何检查指针的类型呢?

Chr*_*phe 5

编译时间差异:

您可以使用模板及其专业化:

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
Run Code Online (Sandbox Code Playgroud)

然后你可以区分你的代码,例如

Name *n; Name1 *n1;
cout << "(1): " << isName(n) << endl;
cout << "(2): " << isName(n1) << endl;
Run Code Online (Sandbox Code Playgroud)

您当然可以isName()根据对象的类别使用in 条件进行处理。

从设计的角度来看,如果您有特定于类的代码,那么将它包装在一些模板中可能更有趣,并使用上面演示的特化,而不是返回布尔值,而是执行要完成的操作,例如

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 Code Online (Sandbox Code Playgroud)

运行时区分:

如果需要在任意指针上决定运行时,则需要动态运行时类型信息。标准 C++ 有 RTTI。但它需要类中至少有一个虚函数。因此,您不能只获取任何指针(例如void*)并找出它指向的数据!您需要一个指向有效多态类的指针。

做到这一点的干净方法是 makeNameName1两者都从具有虚函数的技术公共类继承:

class vvoid {
    virtual void mv() {};
};
Run Code Online (Sandbox Code Playgroud)

然后您可以使用dynamic_cast<typeinfo>来处理您的对象类型,并轻松使用指向基础对象的指针:

void f(vvoid *p){
    cout<<"f("<<p<<"):"<<typeid(*p).name()<< endl;
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以通过为其提供指向派生类的指针来调用此函数:

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

请注意,为了更好的设计,您还可以将任何特定于类的行为嵌入到专用于每个派生类型的虚函数中。但这是一个坚实的类设计的开始,你的假设是:不相关的类。

一种更容易出错的方法是保持这些类中的每一个独立,但确保每个类至少有一个虚函数,以确保它们是多态的并包含 RTTI 信息。

然后,您可以使用危险reinterpret_cast并使用对 RTTI 信息的访问。 这段代码演示了原理:

f(reinterpret_cast<vvoid*>(n)); 
f(reinterpret_cast<vvoid*>(n1));
 
Run Code Online (Sandbox Code Playgroud)

它似乎工作。但是,如果您不小心转换了一个没有虚函数的类,您的代码将在编译时发出警告,但在执行时会非常失败。