BoolanC++面向对象高级编程(下)第一周笔记
一、类相关知识介绍:
template 简单分类:类模板(class template)、函数模板( function template )、成员模板( member template )三类。
1、类模板
顾名思义,这是一个类(class)
举例:
template
class 类名{
// 类定义......
};
其中,template 是声明类模板的关键字,表示声明一个模板,模板参数可以是一个,也可以是多个,可以是类型参数 ,也可以是非类型参数。类型参数由关键字class或typename及其后面的标识符构成。非类型参数由一个普通参数构成,代表模板定义中的一个常量。
举例:
template //type为类型参数,width为非类型参数
class Graphics;
注意:
(1)如果在全局域中声明了与模板参数同名的变量,则该变量被隐藏掉。
(2)模板参数名不能被当作类模板定义中类成员的名字。
(3)同一个模板参数名在模板参数表中只能出现一次。
(4)在不同的类模板或声明中,模板参数名可以被重复使用。
(5)在类模板的前向声明和定义中,模板参数的名字可以不同。
(6)类模板参数可以有缺省实参,给参数提供缺省实参的顺序是先右后左。
(7)类模板名可以被用作一个类型指示符。当一个类模板名被用作另一个模板定义中的类型指示符时,必须指定完整的实参表
类模板实例化
定义:从通用的类模板定义中生成类的过程称为模板实例化。
类模板什么时候会被实例化呢?
(1)当使用了类模板实例的名字,并且上下文环境要求存在类的定义时。
(2)对象类型是一个类模板实例,当对象被定义时。此点被称作类的实例化点。
(3)一个指针或引用指向一个类模板实例,当检查这个指针或引用所指的对象时。
2、函数模板
函数模板的格式:
template 返回类型 函数名(参数列表)
{
函数体
}
<>括号中的参数叫模板形参,模板形参和函数形参很相像,模板形参不能为空。一但声明了模板函数就可以用模板函数的形参名声明类中的成员变量和成员函数,即可以在该函数中使用内置类型的地方都可以使用模板形参名。模板形参需要调用该模板函数时提供的模板实参来初始化模板形参,一旦编译器确定了实际的模板实参类型就称他实例化了函数模板的一个实例。比如swap的模板函数形式为
template void swap(T& a, T& b){},
当调用这样的模板函数时类型T就会被被调用时的类型所代替,比如swap(a,b)其中a和b是int 型,这时模板函数swap中的形参T就会被int所代替,模板函数就变为swap(int &a, int &b)。而当swap(c,d)其中c和d是double类型时,模板函数会被替换为swap(double &a, double &b),这样就实现了函数的实现与类型无关的代码。
2、注意:对于函数模板而言不存在 h(int,int) 这样的调用,不能在函数调用的参数中指定模板形参的类型,对函数模板的调用应使用实参推演来进行,即只能进行 h(2,3) 这样的调用,或者int a, b; h(a,b)。
3、成员模板
本身是一个模板,而它又是类中的一个成员,如下图中黄色部分:
二、标准库之迭代器介绍:
迭代器的简介
(1):迭代器类似于指针类型,它也提供了对对象的间接访问。
(2):指针是C语言中就有的东西,迭代器是c++中才有的,指针用起来灵活高效,迭代器功能更丰富些。
(3):迭代器提供一个对容器对象或者string对象的访问的方法,并且定义了容器范围。
使用迭代器
迭代器和指针不一样,容器和string有迭代器类型同时拥有返回迭代器的成员。比如,容器都有的成员begin和end,其中begin成员复制返回指向第一个元素(第一个字符)的迭代器,而end成员返回指向容器(或string对象)尾元素的下一个位置的迭代器,也就是说end指示的是一个不存在的元素,所以叫end返回的是尾后迭代器。一般我们清楚一个迭代器的准确类型是什么,所以我们都是使用auto或者decltype来定义变量的。
三、名称空间介绍:
命名空间(name space)就是这样一个概念:
C++中采用的是单一的全局变量命名空间。在这单一的空间中,如果有两个变量或函数的名字完全相同,就会出现冲突。当然,你也可以使用不同的名字,但有时我们并不知道另一个变量也使用完全相同的名字;有时为了程序的方便,必需使用同一名字。比如你定义了一个变量 string user_name, 有可能在你调用的某个库文件或另外的程序代码中也定义了相同名字的变量,这就会出现冲突。命名空间就是为解决C++中的变量、函数的命名冲突而服务的。解决的办法就是将你的strTemp变量定义在一个不同名字的命名空间中。
例如: #include
#include
using namespace std;
//using namespace编译指示,使在C++标准类库中定义的名字在本程序中可以使用
//否则,iostream,string 等c++标准类就不可见了,编译就会出错。
//两个在不同命名空间中定义的名字相同的变量
namespace myown1{ string user_name = "myown1"; }
namespace myown2{ string user_name = "myown2"; }
int main()
{
cout<< " " << "Hello, "<< myown1::user_name//用命名空间限制符myown1访问变量user_name << "... and goodbye! "; cout<< " "<< "Hello, " << myown2::user_name //用命名空间限制符myown2访问变量user_name << ".and goodbye! "; return 0;
}