Boolan C++面向对象高级编程(下)第四周笔记
2017-05-11 21:59
211 查看
Boolan极客班C++开发工程师笔记。
对于用户自定义的类类型与其他数据类型实现转换,C++提供了两种方法:
补充:
①类型转换函数只能作为类的成员函数,不能作为友元函数或者普通函数,因为被转换的是本类对象;
②在函数名前面不能指定函数类型,函数没有参数;
③函数中必须有return语句,即函数返回值的类型是函数声明中指定的类型;
④一个类可以定义多个类型转换函数,C++编译器会根据函数名自动调用相应的类型转换函数。
除此之外,我们还需要重载运算符
调用方法:
1.3 explicit关键字
1.1和1.2两种方法共用时会出现歧义,解决方法:
在转换构造函数之前加上explicit,表示不允许将其他类型的数据转换成类对象。
标准库里有很多的仿函数,其实都是些class,所谓的仿函数就是类通过重载()来实现类似函数的功能,返回一个值。
具体的例子见下图
比如我们要测试20个函数,我们可以把每个函数单独放入到一个namespace中去,这样做每个函数都是完全独立的,不用考虑名称上的冲突。
class就是个模板,而成员里还有个模板,即黄色部分,称为成员模板。T1、T2可以变化,U1、U2也可以变化。
为什么我们需要成员模板呢?见下图
鲫鱼和麻雀分别属于鱼类和鸟类的子类,用他们的类对象作为相应父类的初始化值肯定是可以的,但是一旦如上图所示pair类接收鱼类和鸟类类型后,该类的构造函数只能接受鱼类和鸟类作为初始化参数。这个时候我们就需要成员模板来解决pair类接受鲫鱼和麻雀类作为它构造函数的初始化类型。
解释:上面的是泛化,下面的是特化。且下面的都对()进行重载。
偏特化:个数上的偏,范围上的偏。
如下图,个数上的偏特化。一定要从左边到右边,不能跳着来
范围上的偏特化,如下,T是任意类型,现在把它范围缩小成指针,如下
最好的学习方法是把里面的方法全部自己用一遍!
...就是一个所谓的pack(包)
用于template parameters,就是template parameters pack(模板参数包)
用于function parameter types,就是function parameter types pack(函数参数类型包)
用于function parameters,就是function parameters pack(函数参数包)
不要极端地认为全部都使用auto,首先作为初学者在没有完全清楚变量的类型的情况下不建议,其次并不是所有情况下都能使用auto,比如下面这种情况就不能使用auto:
注意点:pass by value和pass by reference的不同作用,前者不改变expression里面的对象,后者可以
1.conversion function(转换函数)
对于系统的预定义基本类型数据,C++提供了隐式类型转换和显式类型转换两种类型转换方式:int a=1,sum=0; double b=1.111; sum=a+b; //隐式转换 sum=(int)(a+b); //显式转换 sum=int(a+b); //显式转换
对于用户自定义的类类型与其他数据类型实现转换,C++提供了两种方法:
1.1 通过类型转换函数进行类型转换;
使用方法与操作符重载相似,定义见如下例子operator double() const { return (double) (m_numerator/m_denominator); }调用方法:
Fraction f(3,5); double d=4+f;//调用operator double() 将f转为0.6
补充:
①类型转换函数只能作为类的成员函数,不能作为友元函数或者普通函数,因为被转换的是本类对象;
②在函数名前面不能指定函数类型,函数没有参数;
③函数中必须有return语句,即函数返回值的类型是函数声明中指定的类型;
④一个类可以定义多个类型转换函数,C++编译器会根据函数名自动调用相应的类型转换函数。
1.2 通过转换构造函数进行类型转换(non-explicit-one-argument ctor);
转换构造函数是将一个其他类型的数据转换成为类的对象,例子:Fraction(int num, int den = 1) : m_numerator(num), m_denominator(den) { }
除此之外,我们还需要重载运算符
Fraction operator + (const Fraction& f) { return .....; }
调用方法:
Fraction f(3,5); Fraction d2=f+4;//调用non-explicit ctor 将4转为Fraction(4,1),然后调用operator+
1.3 explicit关键字
1.1和1.2两种方法共用时会出现歧义,解决方法:
在转换构造函数之前加上explicit,表示不允许将其他类型的数据转换成类对象。
2.pointer-like classes,关于智能指针
把class做的像pointer,但又希望它比pointer多些东西,这就是智能指针。首先,class里面一定有个真正的指针;其次,它得能代表一般的指针,因此就必须有指针的基本使用*和->,这需要操作符重载来实现。3.pointer-like classes,关于迭代器
迭代器的作用是指向容器中的元素,也包含了指针的功能,具体代码见下面两张图。4.function-like classes ,所谓仿函数
设计一个class让它的行为像一个函数。函数是怎么样的呢?有个(),所做出的对象可以接受()。标准库里有很多的仿函数,其实都是些class,所谓的仿函数就是类通过重载()来实现类似函数的功能,返回一个值。
具体的例子见下图
5.标准库中的仿函数的奇特模样
6.namespace
namespace的作用主要是防止函数或者类的名称冲突。比如我们要测试20个函数,我们可以把每个函数单独放入到一个namespace中去,这样做每个函数都是完全独立的,不用考虑名称上的冲突。
7.模板
class template 和 function template前面的笔记中已经提到过。7.1member tempate
先看下图的例子class就是个模板,而成员里还有个模板,即黄色部分,称为成员模板。T1、T2可以变化,U1、U2也可以变化。
为什么我们需要成员模板呢?见下图
鲫鱼和麻雀分别属于鱼类和鸟类的子类,用他们的类对象作为相应父类的初始化值肯定是可以的,但是一旦如上图所示pair类接收鱼类和鸟类类型后,该类的构造函数只能接受鱼类和鸟类作为初始化参数。这个时候我们就需要成员模板来解决pair类接受鲫鱼和麻雀类作为它构造函数的初始化类型。
7.2 specialization,模板特化
泛化就是模板,特化的意思就是指你作为一个设计者,你可能要面对一些特殊的类型要单独处理。解释:上面的是泛化,下面的是特化。且下面的都对()进行重载。
7.3partial specialization,模板偏特化
泛化又分为:全泛化(full specialization)和(partial specialization,模板偏特化(局部特化))偏特化:个数上的偏,范围上的偏。
如下图,个数上的偏特化。一定要从左边到右边,不能跳着来
范围上的偏特化,如下,T是任意类型,现在把它范围缩小成指针,如下
7.4template template parameter,模板模板参数
模板的参数本省也可以是模板,具体代码如下:temeplate<tpyename T, template <typename T> class Container > Class XCls { private: Container<T> c; ...... }; template<typename T> using Lst=list<T,allocator<T>>;如果作为模板参数的模板只需要一个参数,我们可以写成如下格式:
XCls<string,Lst> mylst2;如果需要的参数不止一个,且没有默认值,就不能这么写:
XCls<string,list> mylst1;
8.关于C++标准库
标准库包含了容器(Container),算法(ALgorithms),迭代器(Iterators),仿函数(Functors)等。最好的学习方法是把里面的方法全部自己用一遍!
9.C++11后的一些新语法
9.1variadic template
C++11之前模板必须指定参数个数,现在C++11给出新的语法,模板参数个数可以变动,具体代码如下:void print() { } template<typename T, typename... Types> void print(const &T, const Types&...args) { cout << firstArg << endl; print(args...); }
...就是一个所谓的pack(包)
用于template parameters,就是template parameters pack(模板参数包)
用于function parameter types,就是function parameter types pack(函数参数类型包)
用于function parameters,就是function parameters pack(函数参数包)
9.2 auto
auto是C++中的一个语法糖,可以让编译器自动推算变量类型。不要极端地认为全部都使用auto,首先作为初学者在没有完全清楚变量的类型的情况下不建议,其次并不是所有情况下都能使用auto,比如下面这种情况就不能使用auto:
9.3range-base for
这是for循环的一种新的写法,也是C++11的一种语法糖,依赖于迭代器,格式如下:for (declaration : expression){ statments; }expression必须是一个序列,比如vector,数组,string等。
注意点:pass by value和pass by reference的不同作用,前者不改变expression里面的对象,后者可以
相关文章推荐
- Boolan C++面向对象高级编程(上)第一周笔记
- Boolan C++面向对象高级编程(下)第五周笔记
- Geekband C++面向对象高级编程(上) 第二周笔记 暗影行者
- GeekBand C++ 面向对象高级编程(下) 第三周笔记
- 廖雪峰Python教程 学习笔记11 面向对象高级编程
- 【Python】学习笔记——-8.5、面向对象高级编程:5.使用枚举类
- C++面向对象高级编程笔记01--GeekBand
- Boolan C++面向对象高级编程(上)第二周笔记
- Geekband C++面向对象高级编程(下) 第一周笔记 暗影行者
- 【Python】学习笔记——-8.6、面向对象高级编程:6.使用元类
- 【Python】学习笔记——-8.2、面向对象高级编程:2.使用@property
- C++面向对象高级编程笔记02--GeekBand
- C++面向对象高级编程笔记03--GeekBand
- python学习笔记(七) - 面向对象高级编程
- Javascript高级程序设计第二版第六章--面向对象程序设计(Object-Oriented Programming)简称OOP编程--笔记
- GeekBand C++ 面向对象高级编程(上) 第二周笔记
- (GeekBand)C++面向对象高级编程(上)第一周笔记(1)
- Geekband C++面向对象高级编程(下) 第二周笔记 暗影行者
- Javascript高级程序设计第二版第六章--面向对象程序设计(Object-Oriented Programming)简称OOP编程--笔记
- python2.7学习笔记(10) ——面向对象高级编程