如何在C++中检查指针的类型
how to check the type of a pointer in C++
我有以下代码:
// 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
}
如何查看指针的类型name1
?
Name1和Name不继承,dynamic_cast不能使用,那如何查看指针的类型?
编译时差:
您可以使用模板及其专业化:
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
然后你可以区分你的代码,对于example:
Name *n; Name1 *n1;
cout << "(1): " << isName(n) << endl;
cout << "(2): " << isName(n1) << endl;
当然可以根据对象的class条件使用isName()
进行处理。
从设计的角度来看,如果您有 class 特定代码,将其包装在某些模板中并使用上面演示的特化可能会更有趣,不是为了返回布尔值,而是为了做什么要做,因为 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);
运行时间微分:
如果需要在任意指针上决定运行时间,则需要动态运行-时间类型信息。标准 C++ 具有 RTTI。但是它至少需要在class中有一个虚函数。所以你不能只拿任何指针(例如 void*
)并找出它指向的数据!您需要一个指向有效多态 class.
的指针
最简洁的方法是让 Name
和 Name1
都继承自具有虚函数的技术通用 class:
class vvoid {
virtual void mv() {};
};
然后您可以使用 dynamic_cast
和 <typeinfo>
来处理对象的类型,并轻松使用指向基础对象的指针:
void f(vvoid *p){
cout<<"f("<<p<<"):"<<typeid(*p).name()<< endl;
}
然后您可以通过提供指向派生的 classes:
的指针来调用此函数
Name *n=new Name;
Name1 *n1=new Name1;
f(n); // no risk here, it's automatic conversion to base type
f(n1);
请注意,为了更好的设计,您还可以将任何 class 特定行为嵌入到虚函数中,该函数专用于每个派生类型。但这是可靠 class 设计的开始,您的假设是:不相关 classes.
一种更容易出错的方法是让这些 class 中的每一个保持独立,但确保每个都有至少一个虚函数,以确保它们是多态的并包含 RTTI 信息。
然后您可以使用危险的 reinterpret_cast
并使用对 RTTI 信息的访问。 This code演示原理:
f(reinterpret_cast<vvoid*>(n));
f(reinterpret_cast<vvoid*>(n1));
似乎有效。然而,如果你不小心投射了一个没有虚函数的 class,你的代码将在编译时出现我们的警告,但它在执行时会非常糟糕。
您可以为此使用 typeid:
string typeToFind == "Name1 *";
if(typeToFind.compare(typeid(Name1).name()) == 0) {
//Your code
}
它可能不漂亮,但它确实有用。
您可以使用 boost:boost/type_index.hpp。您可以在下面找到代码:
#include <boost/type_index.hpp>
#include <iostream>
using std::cout;
using boost::typeindex::type_id_with_cvr;
struct TName
{
};
struct TName1
{
};
int main()
{
TName* name;
cout << "param = " << type_id_with_cvr<decltype(name)>().pretty_name() << '\n';
if (type_id_with_cvr<decltype(name)>().pretty_name() == "TName*")
{
std::cout << "Variant 1\n";
}
TName1* name1;
if (type_id_with_cvr<decltype(name1)>().pretty_name() == "TName1*")
{
std::cout << "Variant 2\n";
}
}
结果:
参数 = TName*
变体 1
变体 2
我有以下代码:
// 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
}
如何查看指针的类型name1
?
Name1和Name不继承,dynamic_cast不能使用,那如何查看指针的类型?
编译时差:
您可以使用模板及其专业化:
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
然后你可以区分你的代码,对于example:
Name *n; Name1 *n1;
cout << "(1): " << isName(n) << endl;
cout << "(2): " << isName(n1) << endl;
当然可以根据对象的class条件使用isName()
进行处理。
从设计的角度来看,如果您有 class 特定代码,将其包装在某些模板中并使用上面演示的特化可能会更有趣,不是为了返回布尔值,而是为了做什么要做,因为 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);
运行时间微分:
如果需要在任意指针上决定运行时间,则需要动态运行-时间类型信息。标准 C++ 具有 RTTI。但是它至少需要在class中有一个虚函数。所以你不能只拿任何指针(例如 void*
)并找出它指向的数据!您需要一个指向有效多态 class.
最简洁的方法是让 Name
和 Name1
都继承自具有虚函数的技术通用 class:
class vvoid {
virtual void mv() {};
};
然后您可以使用 dynamic_cast
和 <typeinfo>
来处理对象的类型,并轻松使用指向基础对象的指针:
void f(vvoid *p){
cout<<"f("<<p<<"):"<<typeid(*p).name()<< endl;
}
然后您可以通过提供指向派生的 classes:
的指针来调用此函数Name *n=new Name;
Name1 *n1=new Name1;
f(n); // no risk here, it's automatic conversion to base type
f(n1);
请注意,为了更好的设计,您还可以将任何 class 特定行为嵌入到虚函数中,该函数专用于每个派生类型。但这是可靠 class 设计的开始,您的假设是:不相关 classes.
一种更容易出错的方法是让这些 class 中的每一个保持独立,但确保每个都有至少一个虚函数,以确保它们是多态的并包含 RTTI 信息。
然后您可以使用危险的 reinterpret_cast
并使用对 RTTI 信息的访问。 This code演示原理:
f(reinterpret_cast<vvoid*>(n));
f(reinterpret_cast<vvoid*>(n1));
似乎有效。然而,如果你不小心投射了一个没有虚函数的 class,你的代码将在编译时出现我们的警告,但它在执行时会非常糟糕。
您可以为此使用 typeid:
string typeToFind == "Name1 *";
if(typeToFind.compare(typeid(Name1).name()) == 0) {
//Your code
}
它可能不漂亮,但它确实有用。
您可以使用 boost:boost/type_index.hpp。您可以在下面找到代码:
#include <boost/type_index.hpp>
#include <iostream>
using std::cout;
using boost::typeindex::type_id_with_cvr;
struct TName
{
};
struct TName1
{
};
int main()
{
TName* name;
cout << "param = " << type_id_with_cvr<decltype(name)>().pretty_name() << '\n';
if (type_id_with_cvr<decltype(name)>().pretty_name() == "TName*")
{
std::cout << "Variant 1\n";
}
TName1* name1;
if (type_id_with_cvr<decltype(name1)>().pretty_name() == "TName1*")
{
std::cout << "Variant 2\n";
}
}
结果:
参数 = TName*
变体 1
变体 2