C++中typeid的使用

RTTI(Run-TimeType Information, 运行时类型信息),它提供了运行时确定对象类型的方法。在C++中,为了支持RTTI提供了两个操作符:dynamic_cast和typeid。

The typeid operator provides a program with the ability to retrieve the actual derived type of the object referred to by a pointer or a reference. The typeid operator requires run time type information (RTTI) to be generated, which must be explicitly specified at compile time through a compiler option. The typeid operator returns an lvalue of type const std::type_info that represents the type of expression expr.

typeid是C++的一个关键字,等同于sizeof这类操作符。typeid操作符的返回结果是名为type_info的标准库类型的对象的引用。type_info的name成员函数返回C-style的字符串。

如果表达式的类型是类类型且至少包含有一个虚函数,则typeid操作符返回表达式的动态类型,需要在运行时计算;否则,typeid操作符返回表达式的静态类型,在编译时就可以计算。

使用typeid时应注意:

(1)、typeid运算符允许在运行时确定对象的类型;

(2)、typeid的结果是const type_info&;

(3)、typeid运算符在应用于多态类类型的左值时执行运行时检查,其中对象的实际类型不能由提供的静态信息确定;

(4)、typeid也可在模板中使用以确定模板参数的类型;

(5)、typeid是操作符,不是函数,运行时获知变量类型名称;

(6)、要使用typeid,首先要确保编译器开启了运行时类型检查(RTTI)。

以下是测试代码:

#include "typeid.hpp"
#include <assert.h>
#include <iostream>
#include <string>
#include <typeinfo>
#include <vector>


int func(int a)
{
	return 0;
}

typedef int(*func_ptr)(int);
class Base { public: Base(){} };

int test_typeid1()
{
	char char_ = 'a';
	unsigned char uchar_ = 'b';
	short short_ = 2;
	unsigned short ushort_ = 3;
	int int_ = 1;
	unsigned int uint_ = 4;
	float float_ = 2.0;
	double double_ = 1.0;
	long long_ = 5;
	long long llong_ = 6;
	int array[10] = { 1};
	int* array_header = array;
	std::string string_;
	std::vector<int> int_vector;
	func_ptr f = func;
	Base Base_;
	Base* pBase_ = new Base;
	Base& Base__ = Base_;

	// 对于返回字符串的具体内容,与编译器有关
	std::cout << "char_ type: " << typeid(char_).name() << std::endl; // char_ type: char
	assert(typeid(char).name() == typeid(char_).name());
	
	std::cout << "uchar type: " << typeid(uchar_).name() << std::endl; // uchar type: unsigned char
	assert(typeid(unsigned char).name() == typeid(uchar_).name());
	
	std::cout << "short_ type: " << typeid(short_).name() << std::endl; // short_ type: short
	assert(typeid(short).name() == typeid(short_).name());
	
	std::cout << "ushort_ type: " << typeid(ushort_).name() << std::endl; // ushort_ type: unsigned short
	assert(typeid(unsigned short).name() == typeid(ushort_).name());

	std::cout << "int_ type: " << typeid(int_).name() << std::endl; // int_ type: int
	assert(typeid(int).name() == typeid(int_).name());
	
	std::cout << "uint_ type: " << typeid(uint_).name() << std::endl; // uint_ type: unsigned int
	assert(typeid(unsigned int).name() == typeid(uint_).name());
	
	std::cout << "float_ type: " << typeid(float_).name() << std::endl; // float_ type: float
	assert(typeid(float).name() == typeid(float_).name());

	std::cout << "double_ type: " << typeid(double_).name() << std::endl; // double_ type: double
	assert(typeid(double).name() == typeid(double_).name());

	std::cout << "long_ type: " << typeid(long_).name() << std::endl; // long_ type: long
	assert(typeid(long).name() == typeid(long_).name());

	std::cout << "llong_ type: " << typeid(llong_).name() << std::endl; // llong_ type: __int64
	assert(typeid(long long).name() == typeid(llong_).name());

	std::cout << "array[] type: " << typeid(array).name() << std::endl; // array[] type: int [10]
	assert(typeid(int [10]).name() == typeid(array).name());

	std::cout << "array_header type: " << typeid(array_header).name() << std::endl; // array_header type: int * __ptr64
	assert(typeid(int*).name() == typeid(array_header).name());
	
	std::cout << "string_ type: " << typeid(string_).name() << std::endl; // string_ type: class std::basic_string<char,struct std::char_traits<char>, class std::allocator<char>>
	assert(typeid(std::string).name() == typeid(string_).name());

	std::cout << "int_vector type: " << typeid(int_vector).name() << std::endl; // int_vector type: class std::vector<int,class std::allocator<int>>
	assert(typeid(std::vector<int>).name() == typeid(int_vector).name());

	std::cout << "f type: " << typeid(f).name() << std::endl; // f type : int(__cdecl*)(int)
	assert(typeid(int(*)(int)).name() == typeid(f).name());

	std::cout << "Base_ type: " << typeid(Base_).name() << std::endl; // Base_ type: class Base
	assert(typeid(class Base).name() == typeid(Base_).name());

	std::cout << "pBase_ type: " << typeid(pBase_).name() << std::endl; // pBase_ type: class Base * __ptr64
	assert(typeid(class Base*).name() == typeid(pBase_).name());

	std::cout << "Base__ type: " << typeid(Base__).name() << std::endl; // Base__ type: class Base
	assert(typeid(class Base).name() == typeid(Base__).name());

	delete pBase_;
	return 0;
}


// reference: http://en.cppreference.com/w/cpp/language/typeid
int test_typeid2()
{
	struct Base {}; // non-polymorphic
	struct Derived : Base {};

	struct Base2 { virtual void foo() {} }; // polymorphic
	struct Derived2 : Base2 {};

	int myint = 50;
	std::string mystr = "string";
	double *mydoubleptr = nullptr;

	std::cout << "myint has type: " << typeid(myint).name() << '\n' // myint has type: int
		<< "mystr has type: " << typeid(mystr).name() << '\n' // mystr has type: class std::basic_string<char, struct std::char_traits<char>, class std::allocator<char>>
		<< "mydoubleptr has type: " << typeid(mydoubleptr).name() << '\n'; // mydoubleptr has type: double * __ptr64

	// std::cout << myint is a glvalue expression of polymorphic type; it is evaluated
	const std::type_info& r1 = typeid(std::cout << myint); // 50
	std::cout << "std::cout<<myint has type : " << r1.name() << '\n'; // std::cout<<myint has type: class std::basic_ostream<char, struct std::char_traits<char>>

	// std::printf() is not a glvalue expression of polymorphic type; NOT evaluated
	const std::type_info& r2 = typeid(std::printf("%d\n", myint));
	std::cout << "printf(\"%d\\n\",myint) has type : " << r2.name() << '\n'; // printf(\"%d\\n\",myint) has type : int

	// Non-polymorphic lvalue is a static type
	Derived d1;
	Base& b1 = d1;
	std::cout << "reference to non-polymorphic base: " << typeid(b1).name() << '\n'; // reference to non-polymorphic base: struct 'int __cdecl test_typeid2(void)'::'2'::Base

	Derived2 d2;
	Base2& b2 = d2;
	std::cout << "reference to polymorphic base: " << typeid(b2).name() << '\n'; // reference to polymorphic base: struct 'int __cdecl test_typeid2(void)'::'3'::Derived2

	try {
		// dereferencing a null pointer: okay for a non-polymoprhic expression
		std::cout << "mydoubleptr points to " << typeid(*mydoubleptr).name() << '\n'; // mydoubleptr points to double
		// dereferencing a null pointer: not okay for a polymorphic lvalue
		Derived2* bad_ptr = NULL;
		std::cout << "bad_ptr points to...";  // bad_ptr points to... 
		std::cout << typeid(*bad_ptr).name() << '\n';
	}
	catch (const std::bad_typeid& e) {
		std::cout << " caught " << e.what() << '\n'; // caught Attempted a typeid of NULL pointer!
	}

	return 0;
}

///
// reference: https://msdn.microsoft.com/zh-cn/library/fyf39xec.aspx
template < typename T >
T max(T arg1, T arg2) {
	std::cout << typeid(T).name() << "s compared." << std::endl;
	return (arg1 > arg2 ? arg1 : arg2);
}

int test_typeid3()
{
	class Base {
	public:
		virtual void vvfunc() {}
	};

	class Derived : public Base {};

	Derived* pd = new Derived;
	Base* pb = pd;
	std::cout << typeid(pb).name() << std::endl;   //prints "class Base *" // class 'int __cdecl test_typeid3(void)'::'2'::Base * __ptr64
	std::cout << typeid(*pb).name() << std::endl;   //prints "class Derived" // class 'int __cdecl test_typeid3(void)'::'2'::Derived
	std::cout << typeid(pd).name() << std::endl;   //prints "class Derived *" // class 'int __cdecl test_typeid3(void)'::'2'::Derived * __ptr64
	std::cout << typeid(*pd).name() << std::endl;   //prints "class Derived" // class 'int __cdecl test_typeid3(void)'::'2'::Derived
	delete pd;

	float a = 1.2, b = 3.4;
	max(a, b); // floats compared

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值