c++模板是啥?帮我解释下,谢谢!
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++模板是啥?帮我解释下,谢谢!相关的知识,希望对你有一定的参考价值。
没事翻到“c++模板”这个新名词:模板可是C++的一大技术啊,C++的泛型编程和STL可就靠它了。。。
你有空看一看c++primer吧。。。。
(这是我搜的)我只学过c++的基础不明白这个,就拜托了!
《Thinking in C++: vol1 & vol2》 Bruce Eckel - www.bruceeckel.com
《C++ Template》 David Vandevoorde, Nicolai M. Josuttis
推荐读物:
《modern C++ design》Andrei Alexandrescu
1 介绍
模板是一个包含有未指定类型的函数或类,因此模板并不是一个真正的函数或类,而是代表了一组函数或类,当为模板函数或类指定了一种类型时,就生成了此模板的一个实例,这个操作叫做模板实例化(instantiation)。也可以为某一种类型提供不同于模板的定义,这个称为特化定义(specialization)。对于有多个类型参数的模板,还可以只指定一部分类型,这个称为偏特化定义(partial specialization)。
模板不是实体,因此模板的声明和定义通常都放在头文件中。
2 函数模板
2.1 声明
template<class T>
inline void func(T param)
2.2 函数模板不支持默认类型参数,但支持函数的默认参数
template<class T/* = type,不可以 */>
void func(T param, int size = sizeof(T))
2.3 函数模板显式实例化声明
template void func<int>(int param);
显式实例化后的函数模板不能再有不能转换的类型的调用
显式实例化后的函数模板不能被特化定义
2.4 特化定义函数模板
template<>
void func<int>(int param) //函数模板只支持全特化
特化后是一个实体函数,不再是模板,放在头文件中会导致重定义
2.5 函数模板重载
template<class T>
void func(T param, int i)
template<>
void func(ClassName param, int i)
void func(int i)
这几种func函数的定义,匹配的顺序是非模板函数 -> 特化函数模板 -> 基函数模板。如果不像func<int>(100)这样指定函数模板的参数类型的话,编译器会为函数模板推测出一种类型,如根据100为int类型,编译器会自动调用func<int>,称为隐式特化,而前者则成为显式特化。
为什么函数模板要特化呢?这是因为有时候函数模板并不能处理所有情况,对于个别情况就可以使用特化来替换掉原来模板。
3 类模板
3.1 声明
template<class T>
class ClassName
;
3.2 类方法类外定义
template<class T>
ReturnType ClassName<T>::Func()
;
3.3 非类型(nontype)模板参数
如template<size_t _Nb> class bitset 就是使用size_t类型参数设置位的个数。
可以是常量整数类型(包括枚举)或外部链接(external linkage)对象的指针或引用作为模板参数,不能是浮点型和类对象。
char *s = "hello"; //s不可以,直接使用"hello"亦不可以,因为两个"hello"可能为不同地址
char s[] = "hello"; //s可以
ClassName obj; //obj可以
ClassName<int> obj; //obj可以
什么是一个外部链接对象呢?
关于这个问题,专门转载了SpitFire同志的一篇文章《内部链接和外部链接》到博客中
总的说来,要作为参数必须满足:1、在编译时和链接时可以求值; 2、这个参数如果是指针,则它所指的变量,如果在两个cpp中定义会出链接错误。
不同的参数值构成不同的类型,bitset<100>和bitset<200>是两个类型
3.4 默认参数
template<class T = int, int param = 100>
class ClassName
;
3.5 以模板为类型参数的类模板声明
template<class T>
class Array;
template<class T1, template<class /* 可以省略类型名 */ > class T2>
class ClassName
T2<T1> m_o;
如果T2是带默认参数的:template<class U, int i = 100> class T2; 则在以它为类型参数的类中必须再次指明默认值,如果两个默认值不同以再次声明的为准。
template<class T, int i = 100>
class Array;
template<class T1, template<class, int = 100> class T2>
class ClassName
T2<T1> m_u;
使用:
ClassName<int, Array> obj;
3.6 特化模板类
template<class A, class B>
class ClassName
;
3.6.1 全特化
template<>
class ClassName<int, double>
; //特化后是一个实体类,不再是模板
3.6.2 偏特化
template<class B>
class ClassName<int, B>
; //特化后是一个实体类,仍是模板
template<class A, class B>
class ClassName<A*, B*>
;
3.6.3 类成员函数特化
template<class T>
class ClassName
public: void f();
;
template<>
inline void class ClassName<int> :: f()
//特化类ClassName<int>的f(),T为int类型时优先调用此定义
3.7 模板类里的静态变量
template<class T>
class ClassName
static T a;
定义:
int ClassName<int>::a = 100; /* 定义一个与类模板的类型参数对应的静态变量 */
main()
ClassName<int> o;
3.8 typename关键词
3.8.1 表明紧跟在后面的是类型,而不是其他(如静态变量)
typename vector<T>::iterator it;
3.8.2 定义新类型
typedef typename vetor<T>::iterator Iterator_Type;
3.8.3 代替模板中的class关键词
template<typename T>
class ClassName
;
3.9 模板类中的成员函数模板
template<class T>
class ClassName
public:
template<class T1, class T2> T m_func(T1 a, T2 b);
类外定义:
template<class T>
template<class T1, class T2>
T ClassName<T>::m_func(T1 a, T2 b)
特化
template<>
template<>
int ClassName<int>::m_func(int a, int b) //类必须被一起全特化
调用:
ClassName<int> o;
o.template m_func<int, vector<int> >(100, vector<int>()); //调用时实例化
3.10 继承模板类
template<class T>
class Chlid : public Parent<T>
;
3.10.1 特化继承
class ClassName : public vector<int>
;
3.11 explicit关键字
explicit Y(const X& x);
X x; Y y(x); //显式转换
X x; Y y = x; //隐式转换,编译不通过
第一条语句通过使用显式从X类型转换生成了一个Y类型的对象,后一条语句则使用了隐式转换创建。由于使用了explicit要求必须使用显式,所以编译没有通过。
4 总结
模板加强了使用C++编写可复用代码的能力,但是想学好模板需要花费很大的功夫和精力的,而最难的就是将模板和原有C++面向对象的技术,如继承和多态等,相互融会贯通。
参考资料:http://blog.chinaunix.net/u2/75985/showart.php?id=1300497
参考技术A 简单的说, 模板相当于由编译器负责处理的宏(宏是由预处理器进行简单的文本替换), 在模板中制定参数后编译器会根据制定的参数代入到具体的函数或类里.例:
template <typename t>
t f()
t a;
return a;
在f<int>()处编译器会用int代替t生成函数f的具体定义:
int f()
int a;
return a;
参考资料:Thinking in C++
本回答被提问者采纳MAC地址是啥意思,请详细解释,谢谢!
参考技术A 分类: 电脑/网络 >> 互联网解析:
cache.baidu/c?word=mac%3B%B5%D8%D6%B7&url=%3A%2Elsxyc%2E/Article%5FPrint%2Easp%3FArticleID%3D11&b=0&a=10&user=baidu
MAC地址也叫物理地址、硬件地址或链路地址,由网络设备制造商生产时写在硬件内部。IP地址与MAC地址在计算机里都是以二进制表示的,IP地址是32位的,而MAC地址则是48位的。MAC地址的长度为48位(6个字节),通常表示为12个16进制数,每2个16进制数之间用冒号隔开,如:08:00:20:0A:8C:6D就是一个MAC地址,其中前6位16进制数08:00:20代表网络硬件制造商的编号,它由IEEE(电气与电子工程师协会)分配,而后3位16进制数0A:8C:6D代表该制造商所制造的某个网络产品(如网卡)的系列号。只要你不去更改自己的MAC地址,那么你的MAC地址在世界是惟一的。
MAC地址的作用
IP地址就如同一个职位,而MAC地址则好像是去应聘这个职位的人才,职位可以既可以让甲坐,也可以让乙坐,同样的道理一个节点的IP地址对于网卡是不做要求,基本上什么样的厂家都可以用,也就是说IP地址与MAC地址并不存在着绑定关系。本身有的计算机流动性就比较强,正如同人才可以给不同的单位干活的道理一样的,人才的流动性是比较强的。职位和人才的对应关系就有点像是IP地址与MAC地址的对应关系。比如,如果一个网卡坏了,可以被更换,而无须取得一个新的IP地址。如果一个IP主机从一个网络移到另一个网络,可以给它一个新的IP地址,而无须换一个新的网卡。当然MAC地址除了仅仅只有这个功能还是不够的,就拿人类社会与网络进行类比,通过类比,我们就可以发现其中的类似之处,更好地理解MAC地址的作用。
无论是局域网,还是广域网中的计算机之间的通信,最终都表现为将数据包从某种形式的链路上的初始节点出发,从一个节点传递到另一个节点,最终传送到目的节点。数据包在这些节点之间的移动都是由ARP(Address Resolution Protocol:地址解析协议)负责将IP地址映射到MAC地址上来完成的。其实人类社会和网络也是类似的,试想在人际关系网络中,甲要捎个口信给丁,就会通过乙和丙中转一下,最后由丙 转告给丁。在网络中,这个口信就好比是一个网络中的一个数据包。数据包在传送过程中会不断询问相邻节点的MAC地址,这个过程就好比是人类社会的口信传送过程。相信通过这两个例子,我们就可以进一步理解MAC地址的作用。
与MAC地址相关的命令与软件
在人类社会社交中,我们认识一个人往往只会知道他的姓名,而身份证号码在一般的人际交往中会被忽略。同样在网络中,我们往往只会知道同事或者网友的IP地址,并不会去过多地关心对方的MAC地址。要成长为网络高手,我们可以使用一些方法去了解对方的MAC地址。在这里介绍两种常用的方法,在Windows 9x 中可用WinIPcfg获得,在Windows 2000/XP中可用IPconfig -all获得。
使用命令只能单条获得MAC地址,而且使用起来也是很麻烦的。对于网管人员,更希望有一款简单化操作的软件,我们可以利用“MAC扫描器”远程批量获取MAC地址。它是用于批量获取远程计算机网卡物理地址的一款网络管理软件。该软件运行于网络(局域网、Inter都可以)内的一台机器上,即可监控整个网络的连接情况,实时检测各用户的IP、MAC、主机名、用户名等并记录以供查询,可以由用户自己加以备注;能进行跨网段扫描,能和数据库中得IP和MAC地址进行比较,有修改IP的或使用虚假MAC地址的,都能报警。
更改MAC地址
一般MAC地址在网卡中是固定的,当然也有网络高手会想办法去修改自己的MAC地址。修改自己的MAC地址有两种方法,一种是硬件修改,另外一种是软件修改。
硬件的方法就是直接对网卡进行操作,修改保存在网卡的EPROM里面的MAC地址,通过网卡生产厂家提供的修改程序可以更改存储器里的地址。那么什么叫做EPROM呢?EPROM是电子学中一种存储器的专业术语,它是可擦写的,也就是说一张白纸你用钢笔写了一遍以后就不能再用橡皮擦去了,而EPROM这张白纸用铅笔写后可以再擦去,可以反复改变其中数据的存储器。
当然软件修改的方法就相对来说要简单得多了,在Windows中,网卡的MAC保存在注册表中,实际使用也是从注册表中提取的,所以只要修改注册表就可以改变MAC。Windows 9x中修改:打开注册表编辑器,在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\
Service\Class\Net\下的0000,0001,0002。
Windows 2000/XP中的修改:同样打开注册表编辑器,HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\
Class\4D36E970-E325-11CE-BFC1-08002BE10318 中的0000,0001,0002中的DriverDesc,如果在0000找到,就在0000下面添加字符串变量,命名为“NeorkAddress”,值为要设置的MAC地址,例如:000102030405
完成上述操作后重启就好了。一般网卡发出的包的源MAC地址并不是网卡本身写上去的,而是应用程序提供的,只是在通常的实现中,应用程序先从网卡上得到MAC地址,每次发送的时候都用这个MAC作为源MAC而已,而注册表中的MAC地址是在Windows安装的时候从网卡中读入的,只要你的操作系统不重新安装应该问题不大。
MAC地址的应用
平日身份证的作用并不是很大,但是到了有的关键时刻,身份证就是用来证明你的身份的。比如你要去银行提取现金,这时就要用到身份证。那么MAC地址与IP地址绑定就如同我们在日常生活中的本人携带自己的身份证去做重要事情一样的道理。有的时候,我们为了防止IP地址被盗用,就通过简单的交换机端口绑定(端口的MAC表使用静态表项),可以在每个交换机端口只连接一台主机的情况下防止修改MAC地址的盗用,如果是三层设备还可以提供:交换机端口/IP/MAC 三者的绑定,防止修改MAC的IP盗用。一般绑定MAC地址都是在交换机和路由器上配置的,是网管人员才能接触到的,对于一般电脑用户来说只要了解了绑定的作用就行了。比如你在校园网中把自己的笔记本电脑换到另外一个宿舍就无法上网了,这个就是因为MAC地址与IP地址(端口)绑定引起的。
MAC地址涉及到的安全问题
从上面的介绍可以知道,这种标识方式只是MAC地址基于的,如果有人能够更改MAC地址,就可以盗用IP免费上网了,目前网上针对小区宽带的盗用MAC地址免费上网方式就是基于此这种思路。如果想盗用别人的IP地址,除了IP地址还要知道对应的MAC地址。举个例子,获得局域网内某台主机的MAC地址,比如想得到局域网内名为TARGET主机的MAC地址,先用PING命令:PING TARGET,这样在我们主机上面的ARP表的缓存中就会留下目标地址和MAC映射的记录,然后通过ARP A命令来查询ARP表,这样就得到了指定主机的MAC地址。最后用ARP -s IP 网卡MAC地址,命令把网关的IP地址和它的MAC地址映射起来就可以了。
如果要得到其它网段内的MAC地址,那么可以用工具软件来实现,我觉得Windows优化大师中自带的工具不错,点击“系统性能优化”→“系统安全优化”→“附加工具”→“集群Ping”,可以成批的扫出MAC地址并可以保存到文件。
小知识:ARP(Address Resolution Protocol)是地址解析协议,ARP是一种将IP地址转化成物理地址的协议。从IP地址到物理地址的映射有两种方式:表格方式和非表格方式。ARP具体说来就是将网络层(IP层,也就是相当于OSI的第三层)地址解析为数据连接层(MAC层,也就是相当于OSI的第二层)的MAC地址。ARP协议是通过IP地址来获得MAC地址的。
ARP原理:某机器A要向主机B发送报文,会查询本地的ARP缓存表,找到B的IP地址对应的MAC地址后就会进行数据传输。如果未找到,则广播A一个ARP请求报文(携带主机A的IP地址Ia——物理地址Pa),请求IP地址为Ib的主机B回答物理地址Pb。网上所有主机包括B都收到ARP请求,但只有主机B识别自己的IP地址,于是向A主机发回一个ARP响应报文。其中就包含有B的MAC地址,A接收到B的应答后,就会更新本地的ARP缓存。接着使用这个MAC地址发送数据(由网卡附加MAC地址)。因此,本地高速缓存的这个ARP表是本地网络流通的基础,而且这个缓存是动态的。ARP表:为了回忆通信的速度,最近常用的MAC地址与IP的转换不用依靠交换机来进行,而是在本机上建立一个用来记录常用主机IP-MAC映射表,即ARP表。
如何解决MAC地址带来的安全问题
我们可以将IP地址和MAC地址捆绑起来来解决这个问题。进入“MS-DOS方式”或“命令提示符”,在命令提示符下输入命令:ARP -s 10.88.56.72 00-10-5C-AD-72-E3,即可把MAC地址和IP地址捆绑在一起。这样,就不会出现IP地址被盗用而不能正常使用网络的情况,可以有效保证小区网络的安全和用户的应用。
注意:ARP命令仅对局域网的上网代理服务器有用,而且是针对静态IP地址,如果采用Modem拨号上网或是动态IP地址就不起作用。
不过,只是简单地绑定IP和MAC地址是不能完全的解决IP盗用问题的。作为一个网络供应商,他们有责任为用户解决好这些问题之的后,才交给用户使用,而不是把安全问题交给用户来解决。不应该让用户来承担一些不必要盗用的损失。
作为网络供应商,最常用也是最有效的解决方法就是在IP、MAC绑定的基础上,再把端口绑定进去,即IP-MAC-PORT三者绑定在一起,端口(PORT)指的是交换机的端口。这就需要在布线时候做好端口定时管理工作。在布线时应该把用户墙上的接线盒和交换机的端口一一对应,并做好登记工作,然后把用户交上来的MAC地址填入对应的交换机端口,进而再和IP一起绑定,达到IP-MAC-PORT的三者绑定。这样一来,即使盗用者拥有这个IP对应的MAC地址,但是它不可能同样拥有墙上的端口,因此,从物理通道上隔离了盗用者。
blog163/more?name=effie&id=6022
以上是关于c++模板是啥?帮我解释下,谢谢!的主要内容,如果未能解决你的问题,请参考以下文章
变量地址到底是啥意思啊 C语言 通俗点解释下 O(∩_∩)O谢谢