目录
non-explicit-one-argument constructor
template temeplate parameter 模板模板参数
重载全局 ::new ::new[] ::delete ::delete[]
导读
(1)泛型编程和面向对象编程分属不同的思维,
(2)由继承关系所形成的对象模型,包含this指针,vptr指针,vtbl虚表,虚机制,以及虚函数造成的多态。
转换函数
转换函数 conversion function
- 从一种类型转换成另外一种类型,相互转换。
- 转换函数必须是成员函数,定义转换函数:函数不可以有参数,没有返回参数。
operator 转换类型() const {return 类型}
non-explicit-one-argument constructor
构造函数两个参数,第二个参数有个默认值为1;one-argument表示只需要一个实参就可以调用该函数
如果出现默认构造函数与转换函数并存,那么就会出现模棱两可的情况
explicit-one-argument ctor
//explicit这个关键字基本只出现在构造函数前面,意思是需要明确地需要调用这个构造函数才能调用, //不存在暗中、自动的转换操作。
f+4调用operator+函数,但是4没办法转换成Fraction类型,转换失败
like classes
pointer-like classes 智能指针
- 一个符号作用在对象上就消耗掉了,
->
符号除外,得到的指针对象继续用箭头符号。- 关于标准库STL的迭代器。另外一种类似于指针的类。
reference operator*()const { return (*node).data; }//reference 相当于T& pointer operator->() const { return &(operator*());} //pointer 相当于T*
function-like classes 仿函数
其实就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了。
const T& operator()(const T& x) const {return x;}
标准库中,仿函数都会去继承奇特的base classes.
template模板
class模板
template<typename T> ……
T抽象变量类型。
function模板
template<typename T>函数定义
成员模板 member template
- 在模板类中存在一个新的模板,外面的模板是一个允许变化的东西,如果外部变化项确定,里面的变量又可以变化。
- 把两个继承类构成的pair放进一个有两个基类的pair中是可行的。反之不可以。
- 父类的指针可以指向子类的对象。up-cast。
- 智能指针模板为了实现up-cast,必须使用成员模板。
- 标准库构造函数大多写成这个样子,为的就是让构造函数更有弹性一些
模板特化 specialization
- 泛化,在用的时候进行类型化。
- 设计模板之后,想绑定某种类型,就叫做特例化。指定了特定类型后编译器会根据参数选择相关代码。
cout<<hash<long>()<<endl; 优先调用特化
partial specialization 偏特化
- 个数上的偏。模板有多个模板参数,对部分参数进行特例化
- 范围上的偏。从任意类型,特例化到指针这一种类型。
template temeplate parameter 模板模板参数
关于c++标准库
- 数据结构容器和算法。
- 多使用标准库,写小例子测试标准库。
- 测试是否支持c++11,
cout<<__cplausplus <<endl;
三个主题(标准库中的新语法)
数量不定的模板参数
等到一包参数剩余0个的时候,此时编译器会调用上面的void print()函数
sizeof...(args); //可获得这一包中的个数
auto
ranged-base for
注意传值和传引用
关于const
- 当成员函数的const和non-const版本同事存在是,const object只会(只能)调用const版本,non-const object只会(只能)调用non-const版本。
- const object 调用const 成员函数可行,但是non-const成员函数不可行。
- non-const object 可以调用 const 成员函数,non-const 成员函数。
- non-const 成员函数可以调用const 成员函数,反之则不行。
New 和 Delete
- new 先分配 memory,再调用ctor。
- delete 先调用dtor,再释放memory。
- array new,一定要搭配 array delete。
重载 new 和 delete 函数(编译器调用)
重载全局 ::new ::new[] ::delete ::delete[]
inline void* operator new(size_t_size){/*……分配内存*/} inline void operatpr delete(void* ptr){/*……释放内存*/}
- 上面的重载函数不能放在namespace中,是全局的函数,影响是非常大的。
重载成员函数 new 和 delete
- 成员函数 void* operator new(size_t);
- 成员函数 void operator delete(void*, size_t);
- 成员函数 void* operator new[](size_t);
- 成员函数 void operator delete[](void*, size_t);
- 调用函数时添加了::,调用全局的函数,绕过类所定义的new和 delete版本。
- 关于new 和new[]参数的大小。有虚函数的对象对多一个指针的大小4。
- 对象数组[],对多一个4字节的区域,记录数据的大小是多少。
- 我们可以重载类成员的operator new(),写出多个版本,前提是每个版本的声明都必须有独特的参数列,其中第一个参数必须是size_t,其余参数以new 所指定的placement arguments为初值。出现于new(……)小括号内的便是所谓placement arguments。
- 我们也可以重载类成员operator delete(),写出多个版本,但是绝对不会被delete调用。只有当new所调用的ctor抛出异常,才会调用这些重载的函数operator delete()。它们只能这样被调用,主要用来归还还未完全创造成功的object所占用的memory。即使operatordelete(……)未能一一对应operator new(……)。也不会出现任何报错。
示例接口
重载new(),delete()示例
Basic_String使用new(extra)扩充申请量
- string采用new(extra)进行自己的内存分配,用于实现特定内存结构中引用计数的处理。