深入探究C++ typeid

发布时间:2023-05-20

一、typeid的概念

C++里的typeid是运算符,可以获取一个表达式的类型信息。它的返回值是一个类型信息的引用类型,表示该表达式的数据类型。

// 示例代码
#include <iostream>
#include <typeinfo>
using namespace std;
int main()
{
    int a = 0;
    double b = 1.0;
    const string c = "hello";
    cout << typeid(a).name() << endl;
    cout << typeid(b).name() << endl;
    cout << typeid(c).name() << endl;
    return 0;
}

运行以上代码,输出如下:

i d NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE

可以看到输出的内容都是类型信息,分别对应int类型、double类型和string类型。

二、typeid的使用

C++里的typeid可以用于不同的场景,本节将会介绍一些常见的使用方式。

1. typeid与指针

使用typeid获取指针所指向的类型信息。

// 示例代码
#include <iostream>
#include <typeinfo>
using namespace std;
int main()
{
    int a = 0;
    double b = 1.0;
    const string c = "hello";
    cout << typeid(&a).name() << endl;
    cout << typeid(&b).name() << endl;
    cout << typeid(&c).name() << endl;
    return 0;
}

运行以上代码,输出如下:

Pi Pd PKc

可以看到输出的内容都是指针类型信息。

2. typeid与多态及继承

运用typeid可以方便地获取对象的类型信息,在多态及继承的场景下特别有用。 示例代码如下:

// 示例代码
#include <iostream>
#include <typeinfo>
using namespace std;
class Animal {
public:
    virtual void speak() {}
};
class Cat : public Animal {
public:
    virtual void speak() {
        cout << "I'm a cat." << endl;
    }
};
class Dog : public Animal {
public:
    virtual void speak() {
        cout << "I'm a dog." << endl;
    }
};
void outputType(Animal* a) {
    if (typeid(*a) == typeid(Cat)) {
        cout << "Cat" << endl;
    } else if (typeid(*a) == typeid(Dog)) {
        cout << "Dog" << endl;
    }
}
int main()
{
    Cat c;
    Dog d;
    Animal* a1 = &c;
    Animal* a2 = &d;
    outputType(a1);
    outputType(a2);
    return 0;
}

运行以上代码,输出如下:

Cat Dog

可以看到在outputType()中使用了typeid来判断传入的指针的类型,并输出类型名称。

三、typeid的局限性

虽然使用typeid可以方便地获取对象的类型信息,但是在某些场景下会受到其局限性的影响。

1. typeid与基本类型

在基本类型(例如intdouble等)的场景下,typeid无法提供具体的类型信息。

// 示例代码
#include <iostream>
#include <typeinfo>
using namespace std;
int main()
{
    int i = 0;
    double d = 1.0;
    cout << typeid(i).name() << endl;
    cout << typeid(d).name() << endl;
    return 0;
}

运行以上代码,输出如下:

i d

可以看到输出的内容只包含类型信息,无法提供有用信息。

2. typeid与泛型

在虚拟函数和泛型编程中,使用typeid也会受到一定的限制。

// 示例代码
#include <iostream>
#include <typeinfo>
using namespace std;
template <typename T>
void printType(T t) {
    cout << typeid(t).name() << endl;
}
int main()
{
    int i = 0;
    double d = 1.0;
    const string c = "hello";
    printType(i);
    printType(d);
    printType(c);
    return 0;
}

运行以上代码,输出如下:

i d NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE

可以看到在使用模板函数时,typeid的显示方式与普通的方法有所不同,无法直接获取类型名称。

四、总结

C++中的typeid可以方便地获取类型信息,与面向对象编程的多态机制和继承机制相辅相成,在某些场景下使用效果明显。但值得注意的是,typeid也存在一些局限性,比如在基本类型和泛型编程的场景下效果不佳,需要开发者在使用时进行注意。