第四周 C++面向对象高级编程(下)Boolan

1. 导读

我们的目标

  • 在先前基础课程所培养的正规、大气的编程素养上,继续探讨更多技术。
  • 泛型编程(Generic Programming)和面向对象编程(Object-Oriented Programming)虽然分属不同思维,但它们正是 C++的技术主线,所以本课程也讨论template(模板)。
  • 深入探索面向对象的继承关系(inheritance)所形成的对象模型(Object Model),包括隐藏于底层的 this 指针,vptr(虚指针),vtbl(虚表),virtual mechanism(虚机制),以及虚函数(virtual functions)造成的 polymorphism(多态)效果。

2. 类型转换

转换有两种,一种是转出去,一种是转过来。

2.1 Conversion Function 转换函数

转换函数的作用是转出去,把这个类的值转换成其他的类型。


第四周 C++面向对象高级编程(下)Boolan_第1张图片
Conversion Function
operator double() const {……;}

定义了一个转换为 double 的函数,
没有参数,转换时不会带有参数。
不写返回类型,返回类型就是名称里这个double

  • 如果不改变值,就该加 const,否则后面可能会出错。
  • 只要认为合理,可以设计好几个转换函数。

模板的偏特化?
操作符重载

2.2 只有一个参数的构造函数

只有一个参数的构造函数可以将一个 int 或 float 值转换为该类对象。

2.2.1 non-explicit-on-argument ctor

第四周 C++面向对象高级编程(下)Boolan_第2张图片
non-explicit-on-argument ctor
Fraction (int num, int den=1): m_numerator(num), m_denominator(den) { }

分母默认是1,这样一个值构造为对象时,实际值不变。

Fraction operator+(const Fraction& f) { }

只能分数加分数

Fraction d2=f+4;

4可以转换为 Fraction,因为有一个构造函数只有一个int 参数。

2.2.2 conversion function vs. non-explicit-one argument ctor

第四周 C++面向对象高级编程(下)Boolan_第3张图片
conversion function vs. non-explicit-one argument ctor

当转换函数与非显式声明的一个参数的构造函数同时存在时,就会出现歧义。因为两种方式都可以编译。
多于一条路径可以编译,就会出现歧义,编译器就会报错。

[Error] ambiguous

2.2.3 explicit-one-argument ctor

第四周 C++面向对象高级编程(下)Boolan_第4张图片
explicit-one-argument ctor

显式声明就可以避免这个问题。

explicit Fraction(int num, int den=1):……

此时就会调用构造函数,而不会调用 double 转换函数。

第四周 C++面向对象高级编程(下)Boolan_第5张图片
conversion function

3. 模仿的类

3.1 pointer-like classes

设计一个类,模拟 pointer

3.1.1 关于智能指针

第四周 C++面向对象高级编程(下)Boolan_第6张图片
不同的语法

->用掉后,还有一个 ->,所以

sp->method();
px->method(); //转换完依旧有->

3.1.2 关于迭代器

第四周 C++面向对象高级编程(下)Boolan_第7张图片
迭代器中的指针操作

注意操作符重载
++ -- 适用于指针移动
第四周 C++面向对象高级编程(下)Boolan_第8张图片
Paste_Image.png

return (*node).data;  //取的是node 指向的块的数据
return &(operator()); //返回迭代器中内容的指针,而不是指向迭代器块的 node 的指针。

3.2 function-like classes,所谓仿函数

第四周 C++面向对象高级编程(下)Boolan_第9张图片
function-like classes
第四周 C++面向对象高级编程(下)Boolan_第10张图片
Paste_Image.png
第四周 C++面向对象高级编程(下)Boolan_第11张图片
Paste_Image.png
第四周 C++面向对象高级编程(下)Boolan_第12张图片
Paste_Image.png

unary_function 一个操作数
binary_function 两个操作数

4. namespace 经验谈

第四周 C++面向对象高级编程(下)Boolan_第13张图片
namespace
namespace jj01
{
}//namespace

5. 模板 template

5.1 class template

第四周 C++面向对象高级编程(下)Boolan_第14张图片
class template
template

5.2. Function Template

第四周 C++面向对象高级编程(下)Boolan_第15张图片
Function Template
template 

5.3 Member Template

第四周 C++面向对象高级编程(下)Boolan_第16张图片
Member Template
template 
struct pair {
……
  template 
  ……
}
第四周 C++面向对象高级编程(下)Boolan_第17张图片
Paste_Image.png
第四周 C++面向对象高级编程(下)Boolan_第18张图片
Paste_Image.png
Base1* ptr = new Derived1; //up-cast
shared_ptrsptr(new Derived1); // 模拟 up-cast

5.4 specialization,模板特化

第四周 C++面向对象高级编程(下)Boolan_第19张图片
specialization
template
struct hash {  } ;
template<>
struct hash {   };

泛化对应特化,共性中的个性,用来应对特例。

5.4.1 partial specialization,模板偏特化

又称为局部特化

5.4.1.1 个数的偏

第四周 C++面向对象高级编程(下)Boolan_第20张图片
Paste_Image.png

< >尖括号内叫做模板参数

class vector { };   // Alloc没改变,而 bool 设定了。

一定要从左到右,不能跳,不能135固定,24改变。

5.4.1.2 范围的偏

第四周 C++面向对象高级编程(下)Boolan_第21张图片
范围的偏

指针指向的偏

class c {   };  // 限定为指针

如果 T 是指针,使用偏特化模板。

5.5 template template parameter,模板模板参数

5.5.1 容器需要参数

第四周 C++面向对象高级编程(下)Boolan_第22张图片
容器需要参数
using Lst = list>;

模板需要好几个参数,必须替换

5.5.2 智能指针

第四周 C++面向对象高级编程(下)Boolan_第23张图片
智能指针

对应 SmartPtr,可以是……,不可以是……

5.5.3 这不是模板模板参数

第四周 C++面向对象高级编程(下)Boolan_第24张图片
这不是模板模板参数

已经绑定了,必须是这个,所以就没有模糊地带了。

6. 关于 C++ 标准库

第四周 C++面向对象高级编程(下)Boolan_第25张图片
Paste_Image.png

所有的容易算法都要用一遍。
编译器需要设定到 C++ 11

6.1 variadic templates (since C++11)

第四周 C++面向对象高级编程(下)Boolan_第26张图片
variadic templates

6.2 auto (since C++11)

第四周 C++面向对象高级编程(下)Boolan_第27张图片
auto

用 auto 时一定要让编译器能推出来。

auto ite = find(……)

find 的类型就是 auto 给 ite 的类型。


第四周 C++面向对象高级编程(下)Boolan_第28张图片
Paste_Image.png

auto 不能乱用,太长了、写不出来可以用。
我们一定要知道每个变量的定义是什么。

ranged-bas for (since C++11)

第四周 C++面向对象高级编程(下)Boolan_第29张图片
ranged-bas for
for ( decl : coll ) //左边是一个变量,右边必须是一个collector,容器
for ( int i : { 2, 3, 5, 7 } ){ }
vector vec;
……
for ( auto elem : vec ) { cout << elem << endl ;} //传值
for ( auto& elem : vec ) { elem *= 3; } //传引用,尽量传引用

15. reference(引用)

第四周 C++面向对象高级编程(下)Boolan_第30张图片
reference

声明时一定要有初值,设完之后就不能再变了。


第四周 C++面向对象高级编程(下)Boolan_第31张图片
reference

object 和其 reference 的大小相同,地址也相同(全都是假象)
???那么新建一个 reference 会让程序新占用多少内存呢?

常见用途

第四周 C++面向对象高级编程(下)Boolan_第32张图片
常见用途

函数传参

void func3(Cls& obj) { obj.xxx(); }
func3(obj);

reference 通常不用于声明变量,而用于参数类型和返回类型的描述。
相同声明结构,仅仅传递引用和变量,会导致模糊,签名相同,所以不能同时存在。
是否加const,
???有什么区别?
加 const 会改变签名,是可以定义的。

7. 复合&继承关系下的构造和析构

7.1 Composition(复合)关系下的构造和析构

第四周 C++面向对象高级编程(下)Boolan_第33张图片
Composition(复合)关系下的构造和析构

Container 在外 Component 在内

7.2 Inheritance(继承)关系下的构造和析构

第四周 C++面向对象高级编程(下)Boolan_第34张图片
Inheritance(继承)关系下的构造和析构

Derive在外,Base 在内
由内而外构建
由外而内析构
子类析构函数会自动调用父类析构函数

Inheritance + Composition 关系下的构造和析构

第四周 C++面向对象高级编程(下)Boolan_第35张图片
Inheritance + Composition 关系下的构造和析构

不同编译器可能不同
观察到的结论是先调用 Base,后调用 Component

你可能感兴趣的:(第四周 C++面向对象高级编程(下)Boolan)