一、类型识别
c++是一门静态编译语言,不支持动态类型的获取,但在实际情况中,经常会遇到数据类型的判断。什么是类型识别?其实就是RTTI,运行时类型识别,也就是得到数据的实际定义类型。
二、基本的类型识别
那么在c++中简单的获取类型有几种方法:
在《c++编程思想》第8章“运行时类型识别”中提到了三种基本方法:
1、手动控制(多态机制)
即通过多态机制,利用特定的标记来标识类型。
2、Typeid
库本身提供的一个接口:
Struct test{int a;};
unsigned int uint_ = 4;
assert(typeid(unsigned int).name() == typeid(uint_).name());
const char * info = typeid(new test()).name();
std::cout << typeid(new test()).name() << std::endl;
在linux C语言中提供typeof 这个扩展关键字,实现了类似的功能,但更强大一些。
3、dynamic_cast
这个是用来识别和判断父子类的。前面讲过多次,这里不再赘述。
三、类型的自动推导
c++的类型推导和获取,又有几种方法:
1、c++11中的auto和decltype
这两个关键提供了进一步的类型操作:
Auto a = 10;
Auto b = &a;
decltype适合于表达式或者返回值中对类型的推导判断:
int GetType()
{
return 0;
}
decltype(GetType()) aaa = 100;
2、模板的自动推导
下面再专门分析。
上面的几种方式都可以达到一定的类型处理的目的,但都有着这样或者那样的限制,不过矬子里面拔将军,模板推导还是比较强大的。在分析模板推导前,看看其实语言实现有多么的简单方便,就会明白为什么c++的学习大家都喊难。
相比于其它其它类型语言如c#,它们如何获取和生成对象呢?看一个例子:
//反射例程:
public class RTest {
public string Nation { get; set; }
......
}
Type type = typeof(RTest);
RTest rt = new RTest();
Type t = rt.GetType();
RTest rrt = (RTest)Activator.CreateInstance(type);
四、模板的自动推导机制
模板的自动推导机制是指模板可以根据实际传入的模板参数类型进行模板参数相关类型的自动推断。这个有点拗口,举个例子就明白了:
template<typename T,typename N>
void AlgoControl( T t,N n)
{
}
AlgoControl<int, long>(1, 100);
AlgoControl(2,6);
上面对模板函数AlgoControl的调用有两种情况,第二种就是上面的推导机制的说明,在并没有显示声明模板参数类型时,编译器可以根据传入的2,6自动推导T,N的实际类型。这个例子可能不太形象,再看一个侯捷《STL源码剖析》中的例子:
template<typename Iterator, typename T>
void func_impl(Iterator iter, T t)
{
//下面就可以
T temp;
}
template<typename Iterator>
void func(Iterator iter)
{
//*iter temp;//编译错误
func_impl(iter, *iter);//func的工作全部都移到func_impl里面了
}
int Test( )
{
int i;
func(&i);
return 0;
}
是不是觉得挺强大?但是,它是受限制使用的,在下面的情况中无法使用:
1、无法推导返回值
template<typename T,typename N>
T AlgoControl( N n)
{
int d = 0;
return d;
}
Int d = AlgoControl(6);
2、模板参数和实际传入参数没关系无法推导
template<typename T,typename N>
Int AlgoControl( int a,int b)
{
return sizeof(T);
}
Int d = AlgoControl(1,6);
3、模板参数和实际传入参数位置不对应无法推导
template<typename T, typename N,typename S>
int AlgoControl3(T a, S s)
{
return sizeof(T);
}
int a = AlgoControl3 <char,int,int>(1,3);//第一个参数没有传实际参数
从严格意义上讲不是无法推导,是推导和设想的目标不一致。如果想手动控制还控制不了,也就是说,如果不给定义模板的参数,那么编译都通过不了。
五、总结
通过上述的分析,可以看到类型识别和类型的自动推导,在实际工程中有着很重要的作用。但简单的模板推导和相关函数无法达到想要的目的,这就引出了下一篇《c++的萃取技术》。