对于作者的这个观点,我是有不同意见的。毕竟存在即道理。只是说在不同的场合有不同的作用罢了。
作者在使用跨平台跟嵌入式的微内存中,使用模板却是有一定的受限的。毕竟使用模板在一定程度上是比较占用内存。并且有些ide也是不怎么支持的。
但是这里我得举个反例,说一下模板的好处。
最近在做一个插件管理的借口。
一、描述一下场景:有多种不同类型的插件,假设只有有A和B两种类型的插件,每种类型的插件有n个。然后用户要使用A类型的插件时候我就列出A类型的所有插件供用户选择,反之亦然。但是使用的是嵌入式的wince系统,所以在管理插件方面,当每次用户要使用的时候才去导入插件,并获取插件的信息,这样子过程速度太慢用户体验不好。所以只能在程序运行起来的时候将所有插件的基本信息全部导进来。并且不管插件A或者插件B,它们的基本信息虽然有一定的差异,但是差不多。
二、管理插件的渐进过程:
1、在写第一类插件的导入时候(即A类型插件),简单的写完成。然后在写第二类插件的时候发现跟第一类插件的代码很类似。这时候笔者就想能否统一一下代码,只写一份代码,供所有类型插件管理的使用。但是因为刚开始各类插件定义的接口不是很合理,所以在基本信息方面,各个接口也定义的五花八门。这里就提出了将所有类型的接口的基本信息全部弄成一样的。
2、因为每个类型的接口它们是不同的接口,而为了统一接口就想到了模板的方法。首先在导入接口基本信息方面
template<typename CreateFuncType> OnePlugInfo ImportGeneral(const FileName& plugFileName, const StrVal& createFuncName) { HINSTANCE ins = LoadLibrary(plugFileName); CreateFuncType createFunc = (CreateFuncType)GetProcAddress(ins, createFuncName); OnePlugInfo onePlugInfo = InitPlugInfo(createFunc()); return onePlugInfo; } template<typename PlugType> OnePlugInfo InitPlugInfo(PlugType* plugType) { // 一些初始化的操作 return onePlugInfo; }
如上代码所示,在分析某个插件的时候,每个插件有自己本身的创建导入函数,所以需要使用typename CreateFuncType来进行操作。但是在创建的时候不同的插件有自己本身不同插件类型,但是如果直接在本函数进行初始化则根本无法完成,于是笔者就想到了再通过传参让模板本身去推导对应的创建返回是什么类型。
这样子,在这里也就遵循了每个函数只做一件事的操作。如果不是因为遇到无法推导的问题,也许笔者可能直接在本函数里面写,而不会再去弄一个InitPlugInfo函数来进行初始化,毕竟里面操作的事情不算太多也就6~7行的样子。
三、总结
所以相对不使用模板的方式编码,使用模板的方式进行编码可以节省了很多代码,并且不那么容易出错,即使是出错也只是一处地方而已。并且为了使用统一的代码也会促使自己去统一所有插件的基本信息接口。并且编程的速度提高的N倍。