曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 3949|回复: 1
打印 上一主题 下一主题

typeid() -- 获取对象类型

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34387
跳转到指定楼层
楼主
发表于 2011-12-1 12:00:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
可以通过 typeid 获得一个对象的类型,使用该函数,需要包含 <typeinfo> 头文件。

下面代码在用 VC2010 和 g++ 编译输出结果是不一样的,VC2010 会直接显示出变量类型名称,而 g++ 则不会:
[C++] 纯文本查看 复制代码
#include <iostream>
#include <typeinfo>
using namespace std;

class myclass {
        //...
};

int main()
{
        int i;
        float f;
        myclass ob;

        cout << "The type of i is: " << typeid(i).name() << endl;
        cout << "The type of j is: " << typeid(f).name() << endl;
        cout << "The type of ob is: " << typeid(ob).name() << endl;

        return 0;
}

在 VC 中的输出:
The type of i is: int
The type of j is: float
The type of ob is: class myclass
在 g++ 中的输出:
./typeid
The type of i is: i
The type of j is: f
The type of ob is: 7myclass
可以将 typid 应用于多态基类(多态类是指包含虚函数的类)指针,这也是 typeid 的重要用途之一。这时,typeid 将返回指针所指向对象的实际类型,返回值可能是基类对象或者是基类中派生类的对象。注意,基类指针可以指向基类对象或任何从基类中派生的类的对象。因此,通过 typeid 可以在运行时确定基类型指针指向对象的实际类型,如下面程序所演示:
[C++] 纯文本查看 复制代码
#include <iostream>
#include <typeinfo>
using namespace std;

class base {
    virtual void f() { };  //基类是多态类
    //...
};

class derived1 : public base {
    //...
};

class derived2 : public base {
    //...
};

int main()
{
    base *p, baseob;   //声明一个基类指针和一个基类对象

    derived1 ob1;
    derived2 ob2;

    p = &baseob;
    cout << "p is pointing to an object of type ";
    cout << typeid(*p).name() << endl;

    p = &ob1;
    cout << "p is pointing to an object of type ";
    cout << typeid(*p).name() << endl;

    p = &ob2;
    cout << "p is pointing to an object of type ";
    cout << typeid(*p).name() << endl;
    
    return 0;
}

运行输出:
p is pointing to an object of type class base
p is pointing to an object of type class derived1
p is pointing to an object of type class derived2
在上面程序中,当对多态类型的基类指针使用 typeid 时,可在运行时确定指针指向对象的实际类型。

如果 typeid 应用于非多态类指针时,我们得到的将是指针被声明的类型。也就是说,此时 typeid 不会返回指针所指向对象的实际类型。比如,我们把上面程序里基类中虚函数 f() 前面的 virtual 去掉使之成为一个普通函数时,那么程序将输出:
p is pointing to an object of type class base
p is pointing to an object of type class base
p is pointing to an object of type class base
可见,3 个输出的类型都是 "class base" ,因此此时的 p 是非多态类指针,且 p 的类型是 base 。

由于 typeid 通常应用于被解除引用的指针(如使用了 * 运算符的指针 *p),所以会面临一个指针是空值的情况。如果是空值,那么 typeid 将抛出一个 bad_typeid 类型的异常。

多态类对象引用的用法类似于对象指针。当 typeid 应用于多态类对象引用时,它将返回引用指向对象的实际类型,这时可能是基类型,也可能是派生类型。

当对象引用被作为参数传递给函数时,我们需要经常使用 typeid 来获得对象的实际类型,如下面程序所演示:
[C++] 纯文本查看 复制代码
#include <iostream>
#include <typeinfo>
using namespace std;

class base {
     virtual void f() { };  //基类是多态类
    //...
};

class derived1 : public base {
    //...
};

class derived2 : public base {
    //...
};

//对饮用参数使用 typeid
void WhatType(base &ob)
{
    cout << "ob is referencing an object of tpe ";
    cout << typeid(ob).name() << endl;
}

int main()
{
    int i;
    base baseob;   

    derived1 ob1;
    derived2 ob2;

    WhatType(baseob);
    WhatType(ob1);
    WhatType(ob2);
    
    return 0;
}

运行输出:
ob is referencing an object of tpe class base
ob is referencing an object of tpe class derived1
ob is referencing an object of tpe class derived2
在上面程序中,WhatType() 函数声明了一个 base 类型的引用参数,这就意味着可以将 base 类 或者 base 类的派生类的对象引用作为参数传递给函数。当我们对这个参数使用 typeid 时,我们就可以得到传递给函数的对象的实际类型。

当然了,如果去掉基类中 f() 函数前面的 virtual ,那么我们得到的参数类型还是都为 "class base" 。

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34387
沙发
 楼主| 发表于 2011-12-3 17:04:31 | 只看该作者

typeid 也可以应用于模板类

typeid 也可以应用于模板类。模板类生成对象的类型部分取决于在实例化时我们为模板类的类型参数指定的数据类型。因此,如果模板类使用不同类型的数据来创建两个对象,那么生成的两个对象将是不同的类型。

测试程序1
[C++] 纯文本查看 复制代码
#include "stdafx.h"
#include <iostream>
using namespace std;


template <class T> class myclass {
    T a;
public:
    myclass(T i) { a = i; }
};


int _tmain(int argc, _TCHAR* argv[])
{
    myclass<int> ob1(10), ob2(9);
    myclass<double> ob3(7.2);


    cout << "Type of ob1 is ";
    cout << typeid(ob1).name() << endl;


    cout << "Type of ob2 is ";
    cout << typeid(ob2).name() << endl;


    cout << "Type of ob3 is ";
    cout << typeid(ob3).name() << endl;


    if (typeid(ob1) == typeid(ob2))
        cout << "ob1 and ob2 are the same type\\n";


    if (typeid(ob3) == typeid(ob1))
        cout << "Error\\n";
    else
        cout << "ob1 and ob2 are different types.\\n";


    return 0;
}

运行输出:
Type of ob1 is class myclass<int>
Type of ob2 is class myclass<int>
Type of ob3 is class myclass<double>
ob1 and ob2 are the same type
ob1 and ob2 are different types.
有输出可见,即使由同一模板创建的两个对象,如果由于参数类型不同,那么这两个对象也不同。

测试程序2
[C++] 纯文本查看 复制代码
#include "stdafx.h"
#include <iostream>
#include <cstdlib>
using namespace std;


//figure 是一个模板类
template <class T> class figure {
protected:
    T x, y;
public:
    figure(T i, T j) {
        x = i;
        y = j;
    }
    virtual T area() = 0;
};


template <class T> class triangle : public figure<T> {
public:
    triangle(T i, T j) : figure<T>(i, j) {}
    T area() {
        return x * 0.5 * y;
    }
};


template <class T> class rectangle : public figure<T> {
public:
    rectangle(T i, T j) : figure<T>(i, j) { }
    T area() {
        return x * y;
    }
};


template <class T> class circle : public figure<T> {
public:
    circle(T i, T j=0) : figure<T>(i, j) { }
    T area() {
        return 3.14 * x * x;
    }
};


//创建从类 figure 派生的类的对象
figure<double> *generator()
{
    switch( rand() % 3 ) {
    case 0:
        return new circle<double>(10.0);
    case 1:
        return new triangle<double>(10.1, 5.3);
    case 2:
        return new rectangle<double>(4.3, 5.7);
    }
    return 0;
}




int _tmain(int argc, _TCHAR* argv[])
{
    return 0;
}


int main()
{
    figure<double> *p;
    int i;
    int t = 0, c = 0, r = 0;


    //生成并统计对象
    for (i = 0; i < 10; i++) {        
        p = generator();


        cout << "Object is " << typeid(*p).name();    //运行时类型识别
        cout << ". ";


        //统计对象
        if( typeid(*p) == typeid(triangle<double>)) t++;
        if( typeid(*p) == typeid(rectangle<double>)) r++;
        if( typeid(*p) == typeid(circle<double>)) c++;


        cout << "Area is " << p->area() << endl;
    }


    cout << endl;


    cout << "Objects generated:\\n";
    cout << " Triangles: " << t << endl;
    cout << " Rectangles: " << r << endl;
    cout << " Circles: " << c << endl;


    return 0;
}

运行输出:
Object is class rectangle<double>. Area is 24.51
Object is class rectangle<double>. Area is 24.51
Object is class triangle<double>. Area is 26.765
Object is class triangle<double>. Area is 26.765
Object is class rectangle<double>. Area is 24.51
Object is class triangle<double>. Area is 26.765
Object is class circle<double>. Area is 314
Object is class circle<double>. Area is 314
Object is class triangle<double>. Area is 26.765
Object is class rectangle<double>. Area is 24.51

Objects generated:
Triangles: 4
Rectangles: 4
Circles: 2
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-5-19 09:13 , Processed in 0.061274 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表