conversion function,转换函数
语法:如黄色部分所示,名称“operator+类型”,没有参数,它的返回类型要与名称中的类型一致,并且作者不能写出来。
non-explicit-one-argument ctor
这种构造函数,它是有两形参,且后一个形参有初值,所以它允许被一个实参调用,后面的形参就设为默认值。
所以调用示例中,编译器就会自动转换,以完成编译。
当conversion function和non-explicit-one-argument ctor并存时,调用示例中,就会有两种可以行的完成方法,编译器是没法决定选择使用哪一种的,所以这样会报错。
explicit-one-argument ctor
加了explicit关键字会让编译器不能将4转为Fraction,所以这里调用时编译器也会报错。
class模仿指针
pointer-like classes,关于智能指针
智能指针强化了普通指针所没有的功能,这里暂不详述。
上面的是C++1.0标准库简化后的智能指针;在指针能用到的操作符就是‘*’和‘->’,所以需要重载这两个操作符,而且是必须的。
语法: ‘*’的重载是直接返回指向的内容;而‘->’则是返回实际的指针,但是这样‘->’不就是消耗了吗?然而‘->’它在C++的定义是可以重复使用的,就是说完成重载函数后,它继续起作用。
pointer-like classes,关于迭代器
迭代器也相当于智能指针,它将指向容器的内容;
有所不同的是会有更多的操作符重载‘++’和‘--’,这些操作符作用于指针则是用于移位(内存地址),而这里则是改变在链表中的位置;
迭代器的‘*’的重载,要返回容器内容的数据;
而‘->’的重载则是返回容器内容数据的地址(即是返回指针)。
class模仿函数
function-like classes,所谓仿函数
模仿函数,即是要重载‘()’;
示例中,类模板是pair(一对的),所以写了两个struct,实现pair中两个对象的调用。
调用:
标准库中,仿函数所作用的奇特的base classes
在C++标准库里面,有很多用仿函数,都会继承类似‘binary_function’的classes,它不会占用内存(实际上可能会占用为1)。
关于namespace
由于,在实际的开发团队中,各部门之间所写的代码,难免会有重名的情况出现;
或者自己写的测试程序也会有重名的情况,利用命名空间namespace,去解决重名情况,这样一来就可以在不同的namespace中都使用自己习惯的名称,不用再苦恼为变量和函数如何命名的问题。
关于模板
class template,类模板
所谓class template,就是在设计class时,把那些你认为允许使用者任意指定的类型抽出来,用自定义的关系字代替(这里用‘T’);
在调用时,就像上面一样,把指定类型写在‘<>’里面放在类名的后面。
语法:用template,表示T为未指定类型(可以是类,也可以是普通的数据类型)
function template,函数模板
所谓函数模板,就是允许函数不指明是哪一种类型调用和返回;
在调用时,编译器会进行实参推导,用来确定调用的类型;
要注意的是对象的类的功能要完善,要用到的操作符一定要重载。
语法:用template,表示T为未知的类型;
(在模板定义的语法中关键字class和typename的作用是完全一样的)
member template,成员模板
所谓成员模板(也可以说是模板成员),就是说它是类的成员,而且它本身又是一个模板。
特化模板
最前面的是普通的类模板,可以接收所有的类型,称为泛化模板;
而后面的三个则是特化模板,它是泛化模板中的特例,只能接收指定的类型;(如果泛化模板和特化模板同时存在,编译器会先检测特化模板)
但这样做不是跟不用模板一样吗?不一样,这样做可以为每种类型写不一样的内容。
模板偏特化(局部特化)
个数上的部分特化,将部分确定的形参类型和不确定的模板参数类型的标识符依次排序。(左边的一定要是确定的形参类型,而不能有非模板和模板参数穿插在里面)
范围上的局部特化,例如指针是对应类型的部分;
上面便是实现方法,在调用时编译器会判断,是否实参为指针形,而选择下面的一个(上一个和下一个的标识符没有直接的关联,可以写成右边的)
template template parameter,模板模板参数
上面的class,就是所谓的模板模板参数的写法,黄色的部分,是它与之不同的之处;
黄色部分表示,Container自身为模板,并且用第一模板参数‘T’作为它里面的参数类型(黄色里面的‘T’,就是指第一个模板‘T’);
但这样是还不是调用的,还需要增加中间的两行才可以(具体原因,会在下一个相关的章节详述)
对于上面的例子,第二模板参数也使用第一模板参数‘T’,作为它里面的参数;
但它不是模板模板参数,因为它的第二模板参数是预置了默认值,不完全是模板,
在调用时,它可以不写,而使用默认值,也可以写(第二个调用便是),但这样就不用理会第一参数的类型,而可以写上需要的类型。
这一点就可以与模板模板参数的定义分开。
关于C++标准库
在C++的标准库里面,已经涵盖了很多种容器(数据结构)和算法,标准库是很棒的团队写的,所以我们要善用标准库,而不是全都自己去写。
学习标准库的最好方法,就是自己写一个小程序,应用到标准库的每一个函数,而不是只去看网上相关的例子(光看,不实践)
C++11新标准
variadic template (数量不定的模板参数)
上面第2函数的第二模板参数便是,用typename...(记得是在typename后面加三个点),声明使用variadic template,表示接收一个参数包(里面有个数不定的参数)
接下来,在第2函数的第二个形参,相应的也需要的在后面,加上三个点,表示不定个数的参数包。
在调用时,也需要在参数包名称的后面加上三个点。
例子中的第2函数,会被辗转调用,直到把42输出是,参数包args...内没有参数了,print(args...)调用的就会是第1函数,从而结束运行。
例子是函数,当然,类也可以使用这个C++2.0的新特性。
auto
它的作用是,在变量声明时赋值的情况下,能让编译器通过判断值的类型,来确定变量的类型。
若在变量只声明不赋值时,编译器则无法确定变量的类型,所以最后的用法是不允许的。
ranged-base for
注释:decl表示变量,coll表示容器
例子中,for的里面的‘{}’表示容器(它也是C++11的新标准)
例子的for语句将会实现的是,把容器coll里的内容,逐个赋值给变量decl,直到容器遍历完成。
若想要改变容器内的值,则需要使用pass by reference。
关于reference
reference在定义时一定要有初值,而且不能被改变,直到它的生命结束。
例子中,r是代表x的,r拥有x的所以特性,也就是说r和它所代表的x的大小相同,地址相同(不过这是编译器所制造的假象)
二者不能并存的原因,是函数签名signature相同,使程序产生歧义Ambiguity,导致编译模棱两可;
函数灰色部分可以加const,const也是函数签名的一部分,所以二者其中一个加上const,就可以使它们两者并存。