30.模板术语
这一条是很简单的一条,主要是明确不同程序员所指的内容的正确性。
template
class Heap{…}; //Heap是一个模板名字
//…
Heap
//Heap
模板名字和模板id之间的区别,前者只是一个简单的标识符,后者则是指附带有模板实参列表的模板名称。
31.泛型算法
一个泛型算法就是一个以这种方式设计的函数模板:根据使用上下文,它可以在编译期容易且有效的进行定制。我们来对比一下就知道为什么说STL是C++里面很经典的东西了~
template
void slowSort(T a[],int len)
{
for(int i=0;i
for(int j=i;j
{
T tem(a[j]);
a[j]=a[i];
a[i]=tem;
}
}
上面这个顶多算是一个函数模板,简单来说还不够“泛”(比如,它假定是对数组,或一组对象,并且满足”=”操作符),其实和泛型算法还有很大的差别。我们来看看标准库里面怎样实现排序的:
template
void slowSort(For b,For e,Comp less) //Comp代表了怎样对待处理数据进行处理的函数
{
for(For i(b);i!=e;++i) //注意此处使用”!=”和”++i”
for(For j(i);j!=e;++j)
if(less(a[i],a[j]))
swap(a[j],a[i]);
}
template
void slowSort(For b,For e)
{
for(For i(b);i!=e;++i) //注意此处使用”!=”和”++i”
for(For j(i);j!=e;++j)
if(a[i]>a[j]))
swap(a[j],a[i]);
}
//…
std::list
//…
slowSort(union.begin(),union.end(),PopComp());
slowSort(union.begin(),union.end());
作者感慨的说,复杂的软件设计几乎总是群体努力的结果。
32.包含哨位
在产品级的C++应用中往往会用到大量的头文件 ,宁企鹅许多头文件中还包含其他头文件。在这些复杂情况中很容易就会产生头文件的重复包含,这会大大加长编译时间,所以我们往往通过宏定义来避免出现这种情况。
#ifndef HDR1_H
#define HDR1_h
//头文件的内容….
#endif
要注意这项功能只有一个头文件预处理符号(如上面的HDR1_H)的确和一个头文件关联时才会起到作用,因此,建立一个简单的、标准的命名约定,从而允许根据被守卫的头文件名来产生头文件预处理符号来说的确很有意义,尤其是对于大型的项目。
我们还可以用另外一种方式:
#ifndef HDR1_H
#include “hdr1.h”
#endif
补充:对于最近出现的编译器都会有些特殊的编译器选项来保证一个头文件在编译时只包含一次,比如VC++里面#pragma once
只要在一个头文件的开始添加上#pragma once就可保证改头文件被包含一次。
33.可选的关键字
- 重写了基类虚成员函数的派生类成员函数中可选的使用了vritual关键字(本人感觉还是不写的方便点,也防止浏览时误认为是虚基类)
- 声明operator new/delete以及array new/delete成员函数时,static关键字是可选的,因为这些函数是隐士静态的
- 在一个木板的头部,关键字typename和class可以互换使用,表示一个模板参数是一个类型名字(
/ ),在这种上下文中二者毫无区别。然而,许多专家级的c++程序员使用typename向人们指明该模板实参可以使任何类型,而class用来指明该类型实参必须是一个类类型。 - 在“古”时候,register关键字用用于向编译器说明某个变量将会频繁的使用,因此建议将其放置于一个寄存器里。而且,试图获取一个声明为register存储类型的地址是非法的。但是,由于每个人来说一个变量到底怎样才算经常使用是有差别的,所以这个地方确实有点差异。但是,对于现在的编译器则整齐划一的忽略了程序员的这个建议。使用register并不会产生任何差异。
//TODO::还有几点关于类模板的知识点,在后续的时候我会再添上….