侯捷老师C++课程下半部分。本课程是对之前课程中所提的一些东西的补充,以及C++11新特性的一些讲解。
Lesson1 介绍
本课程会讲的内容:
- 泛型编程
- 深入探索面向对象继承关系所形成的的对象模型,包括隐藏在底层的this指针,虚指针,虚表等。
Lesson2 转换函数 conversion function
转换有两个方向,一个是我这个类型转换成那个,也可以是那个转换成这个。
现在有一个分数class:
黄色的部分就是转换函数。转换肯定不会改变数据的值,所以要加上const。
不需要返回值类型,因为很明确,函数名就表示了要转换的那个类型。
调用的时候:
Fraction f(3,5);
double d=3+f;
在这里,编译器会首先找一个全局函数,看是不是有+
运算符重载函数,如果没有,就去找转换函数,此时再调用转换函数。
只要你认为合理,可以有很多个转换函数。
non-explicit-one-argument ctor
再来看下面这种情况,构造函数前可以加 explicit
关键字。现在是不加这个关键字的情况。
首先构造函数有两个形参,其中一个给了初值。其实调用的时候,只要给一个实参即可。
Fraction f(3,5);
double d=f+3;
这时在执行上述代码时,类中的运算符重载函数并没有分数加整型数这种情况,只有分数加分数。当看到没有这种重载+
这种函数,所以就想着可不可以把整型数3变为Fraction,那就看其构造函数,如果满足构造函数的参数,那么就会调用构造函数来进行类型的转换。这是让其他类型的数据转化成本类型。
但是当有下面这种情况时,既可以用构造函数,又可以用类型转换函数。此时编译器会报错,因为它不知道调用哪个函数。
explicit-one-argument ctor
当在构造函数加上关键字explicit
后,就可以避免上述问题发生。expilcit意思为明白的,明确的。在该关键字的限制下,构造函数就是创建新对象的时候调用,告诉编译器,不要在隐形转换的时候调用。
看下面的例子:
这里出错显示:[Error]conversion from 'double' to 'Fraction' request
,在一开始看到f+4
时,编译器会先找重载运算符函数,发现只有分数加分数,所以要把4转化成分数,但是该构造函数前加上了explict,所以不能走这条路。于是又找到类型转换函数,这条路可以走通,最终得到结果4.6,但是要把4.6赋值给d2,没有这种类型转换函数。
Lesson3 pointer-like classes
设计一个class,让它像指针。为什么这么做呢,就是想设计一个比指针功能更强大的东西。
关于智能指针
shared_ptr是一个智能指针的模板类。我们写了一个Foo类,然后创建一个智能指针sp,这个过程中shared_ptr<Foo> sp(new Foo)
会调用构造函数,向智能指针中传入指针的值。
*sp
调用了重载运算符*函数。返回值为该对象。
这里要注意sp->method()
,这句话会调用重载运算符函数,返回值是一个指针,虽然->
在调用函数后就已经“消耗了”,返回的是一个指针,相当于已经没有了->
,但是为了保证符号的一致性,总不能写成sp->->method()
,所以它就相当于px->method()
,就不用再写一遍了。
关于迭代器
迭代器也是一种智能指针,指向容器中的一个元素。但是和上面说的智能指针略有不同。
它不但要处理* ->
,还要处理 ++ -- == !=
等。
Lesson4 function-like classes
写一个class,让它像一个函数。即仿函数。
形式为typername()()
,前面的括号是创建一个临时对象,然后再加一个括号,是调用运算符重载函数。
Lesson5 member template 成员模板
模板主要分三大类:
- class template
- function template
- member template
下面是member template的代码:
在类中,构造函数为一个模板函数,这样在初始化的时候,会有更大的弹性。 因为模板函数不需要特别指定具体的类型,会自动推导。所以只在外面写好要创建的类,待传入初始化值时,类中的模板函数会自动推导出初始化值得类型。
Lesson6 模板特化(specialization)
在使用模板的时候,我们可以随机指定任何的类型,然后把该类型放到模板中。这就是泛化的概念。
但是有时候,我们想在一些特定的类型时,不使用泛化的模板,而是有一些特别之处。这就是模板特化。
语法:
在使用的时候,例如上面的例子,编译器会找,泛化也可以,特化也可以,正如代码所写,特别指定的类型是long,所以就找到对应的模板。
Lesson7 偏特化(partial specialization)
个数上的偏
语法:
在这里,我们只想让模板中的某几个类型特化,如上,我们想让T特化,而且Alloc有默认类型。
那么语法就是,在下面写上不特化的类型(特化的类型那块还是空着,对比全特化,尖括号里全是空)。
范围上的偏
泛化的模板输入的类型可以是任意的,当我们想缩小一下范围,指定具体的某几个类型,例如,是指针类型,但是没有说明是什么的指针。
语法:
这是后,obj1用的就是泛化的模板。obj2用的是特化的模板。
Lesson8 template template parameter 模板模板参数
Container可以是任意的字。模板模板参数就是,尖括号内第一项的模板参数,告诉有T这个模板类型存在。然后第二项模板参数是一个模板类,该模板类还需要模板参数,这样就形成了模板模板参数。
模板类的名字我们可以指定(因为类就可以当做是一个数据类型)
就是很绕,但其实不难的。
然后我们使用的时候,是这样的:
XCLs<string,list> mylst1;
这句话虽然是报错的,但是我们写的模板模板参数啥的都没有问题,报错的主要原因是list
这个容器的模板参数有好几个,虽然模板参数是有默认值的,但是在模板中使用必须要指出。所以得加上中间那两句话。
模板中参数前面的关键字,有时候是typename,有时也可以是class,有什么区别呢。注意这里只有在 <>
中,定义模板参数的时候,是共通的。如template<typename T,class U>
,这是共通的。但是当像上面写模板模板参数的时候,用到的class,这是不能共通的,这里的class表示是一个类,而不是一个模板参数。
Lesson9 关于标准库
任何语言的标准库都十分重要,应该能熟练的使用。
C++的标准库主要有以下几个部分:
程序就是靠算法和数据搭建起来的,algorithms+data=program。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)