侯捷老师C++学习笔记——大气编程(下)

侯捷老师C++课程下半部分。本课程是对之前课程中所提的一些东西的补充,以及C++11新特性的一些讲解。

Lesson1 介绍

本课程会讲的内容:

  • 泛型编程
  • 深入探索面向对象继承关系所形成的的对象模型,包括隐藏在底层的this指针,虚指针,虚表等。

Lesson2 转换函数 conversion function

转换有两个方向,一个是我这个类型转换成那个,也可以是那个转换成这个。

现在有一个分数class:

image-20211110201213702

黄色的部分就是转换函数。转换肯定不会改变数据的值,所以要加上const。

不需要返回值类型,因为很明确,函数名就表示了要转换的那个类型。

调用的时候:

Fraction f(3,5);
double d=3+f;//调用operator double()将f转为0.6

在这里,编译器会首先找一个全局函数,看是不是有+运算符重载函数,如果没有,就去找转换函数,此时再调用转换函数。

只要你认为合理,可以有很多个转换函数。

non-explicit-one-argument ctor

再来看下面这种情况,构造函数前可以加 explicit 关键字。现在是不加这个关键字的情况。

首先构造函数有两个形参,其中一个给了初值。其实调用的时候,只要给一个实参即可。

image-20211110202233538
Fraction f(3,5);
double d=f+3;

这时在执行上述代码时,类中的运算符重载函数并没有分数加整型数这种情况,只有分数加分数。当看到没有这种重载+ 这种函数,所以就想着可不可以把整型数3变为Fraction,那就看其构造函数,如果满足构造函数的参数,那么就会调用构造函数来进行类型的转换。这是让其他类型的数据转化成本类型。

但是当有下面这种情况时,既可以用构造函数,又可以用类型转换函数。此时编译器会报错,因为它不知道调用哪个函数。

image-20211110203235669

explicit-one-argument ctor

当在构造函数加上关键字explicit后,就可以避免上述问题发生。expilcit意思为明白的,明确的。在该关键字的限制下,构造函数就是创建新对象的时候调用,告诉编译器,不要在隐形转换的时候调用。

看下面的例子:

image-20211111065659372

这里出错显示:[Error]conversion from 'double' to 'Fraction' request ,在一开始看到f+4时,编译器会先找重载运算符函数,发现只有分数加分数,所以要把4转化成分数,但是该构造函数前加上了explict,所以不能走这条路。于是又找到类型转换函数,这条路可以走通,最终得到结果4.6,但是要把4.6赋值给d2,没有这种类型转换函数。

Lesson3 pointer-like classes

设计一个class,让它像指针。为什么这么做呢,就是想设计一个比指针功能更强大的东西。

关于智能指针

image-20211111072414463

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的代码:

image-20211111080704918

在类中,构造函数为一个模板函数,这样在初始化的时候,会有更大的弹性。 因为模板函数不需要特别指定具体的类型,会自动推导。所以只在外面写好要创建的类,待传入初始化值时,类中的模板函数会自动推导出初始化值得类型。

Lesson6 模板特化(specialization)

在使用模板的时候,我们可以随机指定任何的类型,然后把该类型放到模板中。这就是泛化的概念。

但是有时候,我们想在一些特定的类型时,不使用泛化的模板,而是有一些特别之处。这就是模板特化。

语法:

image-20211111082640173

在使用的时候,例如上面的例子,编译器会找,泛化也可以,特化也可以,正如代码所写,特别指定的类型是long,所以就找到对应的模板。

Lesson7 偏特化(partial specialization)

个数上的偏

语法:

image-20211111083230419

在这里,我们只想让模板中的某几个类型特化,如上,我们想让T特化,而且Alloc有默认类型。

那么语法就是,在下面写上不特化的类型(特化的类型那块还是空着,对比全特化,尖括号里全是空)。

范围上的偏

泛化的模板输入的类型可以是任意的,当我们想缩小一下范围,指定具体的某几个类型,例如,是指针类型,但是没有说明是什么的指针。

语法:

image-20211111083910643

这是后,obj1用的就是泛化的模板。obj2用的是特化的模板。

Lesson8 template template parameter 模板模板参数

image-20211111084146414

Container可以是任意的字。模板模板参数就是,尖括号内第一项的模板参数,告诉有T这个模板类型存在。然后第二项模板参数是一个模板类,该模板类还需要模板参数,这样就形成了模板模板参数。

模板类的名字我们可以指定(因为类就可以当做是一个数据类型)

就是很绕,但其实不难的。

然后我们使用的时候,是这样的:

XCLs<string,list> mylst1;

这句话虽然是报错的,但是我们写的模板模板参数啥的都没有问题,报错的主要原因是list这个容器的模板参数有好几个,虽然模板参数是有默认值的,但是在模板中使用必须要指出。所以得加上中间那两句话。

模板中参数前面的关键字,有时候是typename,有时也可以是class,有什么区别呢。注意这里只有在 <>中,定义模板参数的时候,是共通的。如template<typename T,class U> ,这是共通的。但是当像上面写模板模板参数的时候,用到的class,这是不能共通的,这里的class表示是一个类,而不是一个模板参数。

Lesson9 关于标准库

任何语言的标准库都十分重要,应该能熟练的使用。

C++的标准库主要有以下几个部分:

image-20211111093957659
  • 容器:就是数据结构。
  • 算法:实现一些功能的方法。

程序就是靠算法和数据搭建起来的,algorithms+data=program。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值