一、导读
(1)泛型编程和面向对象编程分属不同的思维。
(2)由继承关系所形成的对象模型,包含this指针,vptr指针,vtbl虚表,虚机制,以及虚函数造成的多态。
二、conversion function 转换函数
(1)通过指定关键字operator,如operator type() const {} ,并在其后加上转换的目标类型后,我们就可以声明转换函数。转换函数必须是成员函数,它的声明不能指定返回类型和参数列表。
分数Fraction型转换成double型,返回类型不用写,默认为double型,没有形参。
三、non-explicit-one-argument constructor
(1)explicit这个关键字基本只出现在构造函数前面,意思是需要明确地调用这个构造函数才能调用,编译器不再存在暗中、自动的转换操作。
(2)构造函数两个参数,第二个参数有个默认值为1;one-argument表示只需要一个实参就可以调用该函数。
四、pointer-like classes 智能指针
(1)设计一个class,使它的行为像指针。主要包括两种:智能指针和迭代器。
(2)shared_ptr智能指针类的行为与指针类似:需要重载操作符 * 和操作符->。
(3)迭代器作为一个种智能指针,除了需要重载操作符 * 和操作符->外,还需要重载其他操作符,例如,操作符 ++。
(4)智能指针在C++11版本之后提供,包含在头文件<memory>中,shared_ptr、unique_ptr、weak_ptr。
五、function-like classes 仿函数
(1)设计一个class,使它的行为像函数。
(2)在类中实现一个operator()重载,这个类就有了类似函数的行为,就是一个仿函数类了。
六、namespace经验谈
不同的命名空间用于规避不同团队开发的接口的冲突。
七、class template 类模板
八、function Template 函数模板
九、member Template 成员模板
- 成员模板:模板里面再定义模板。
- 标准库里大量使用成员模板,用于改善类灵活性(up-cast)。
在这个例子中,成员模板的类型,需要满足一个条件:T1可以放进U1.first中,T2可以放进U1.second中,即U1.first的类是T1的基类,U1.second的类是T2的基类。
十、specialization 模板特化
(1)template <>中,<>里面没有类型的参数了,参数类型在后面绑定,即特化。
(2)template <class T>中,T的类型未被指定为特定类型,就是泛化。
编译器编译时,会确定模板是否存在特化,如果存在特化,优先使用特化代码。
十一、partial specialization 模板偏特化
- 模板的偏特化分为两种情况:个数的偏,范围的偏。
- 不管是模板特化,还是模板偏特化,都是将模板具体化的一些情况。
- class vector<bool, Allocator> { //…//};
这个偏特化的例子中,一个参数被绑定到bool类型,而另一个参数仍未绑定需要由用户指定。
- 范围偏特化:将原模板的类型T(泛指所有类型),范围缩小为指针类型(当然也可以是其他情况)。
在编译C<string*> obj2时,编译器将使用指针类型的模板。
十二、模板模板参数
(1)模板的参数类型也是模板。
(2)只有在模板<>尖括号中,关键字typename与class是才通用的。
(3)带模板模板参数的模板,在第一次具体模板参数时,模板模板参数仍然未明确。
十三、关于C++标准库
- 容器Container,就是数据结构:数组,列表,队列......
- 通过查看编译器宏 __cplusplus可以查看编译器支持的版本(199711L,201103L等)
- C++11 compiler support shootout: Visual Studio, GCC, Clang, Intel
网站http://cpprocks.com/c11-compiler-support-shootout-visual-studio-gcc-clang-intel/
十四、三个主题( 和C++11有关)
- variadic templates 数量不定的模板参数,即模板参数可变化。
例:template <typename T,typename...Types>
获取模板参数个数方法:sizeof...(Types)。
- auto 编译器可以推导变量的类型,就在变量前面加上auto,以代替变量类型。
- ranged-base for 即for循环的新形式:
decl:定义一个变量;coll:指定一个容器。
例子:
变量遍历可以传引用。
十五、reference
- 指针符号*是靠近类型,还是靠近变量合适?建议靠近类型。
- int& r =x; //r代表x, 逻辑上把r看作一个变量,但底层里,r的实现是指针。
r必须要有初值。
r不能再代表其他变量。
编译器会处理对r进行处理,使其object和reference的大小相同,地址也相同(全都是假象),即:
-
-
- sizeof(r) == sizeof(x)
- &x == &r
-
- reference是一种漂亮的pointer。
- reference通常不用于声明变量,而用于参数类型和返回类型的描述。
- 返回值、reference不能用于区分函数签名。
- 函数const是函数签名的一部分。
-------------------下面讲的是对象模型Object Model,即class和class之间的关系-------------------
十六、复合&继承关系下的构造和析构
十七、关于vptr和vtbl
- vptr虚函数指针:指向虚函数列表(vtbl)头的指针。
- vtbl 虚表:存放vptr的列表。
- 每个有虚函数类的对象,都有一个vptr。
- 动态绑定:从对象指针,到vtbl虚表,到对象虚函数。
- 编译器将代码编译成动态绑定形式的条件:
通过指针(引用)调用;向上转型(子类到父类);调用的是虚函数。
- 多态、动态绑定、虚指针都是相同的东西。
十八、关于this指针
(1)Template Method(模板方法设计模式)。
(2)this可以理解为一个指针,也可以看作一个对象this object。
(3)在C++里,所有的非static成员函数,都有一个隐藏的参数 this。
十九、关于dynamic binding
动态绑定的发生,需要满足三个条件:1.指针(引用)调用;2.向上转型;3.调用虚函数。
-------------------------对象模型Object Model内容结束,以下是追加的课题 --------------------------
二十、谈谈const
- const是函数签名的一部分。
- COW: Copy On Write,需要修改数据时,单独拷贝一份数据进行修改。
- 当成员函数的const和non-const版本同时存在时,const object只会(只能)调用const版本,non-const object只会(只能)调用non-const版本。
二十一、关于new, delete
- 创建新对象时,先分配memory(内部调用malloc函数),再调用ctor(构造函数)。
- 释放新对象时,先调用dtor(析构函数),再释放memory(内部调用free函数)。
- array new一定要搭配array delete。
二十二、operator new,operator delete
- 重载 ::operator new, ::operator delete, ::operator new[], ::operator delete[],将接管全局的new和delete函数。
- 这些重载函数,是给编译器调用的:当重载这些函数之后,编译器将不会调用全局的new和delete函数。
- 这些重载函数,不可以被声明与一个namespace内。
- operator new, ::operator new[] 重载函数需要有一个大小参数。
- 小心,重载全局函数,影响将非常大。
- ::operator new, ::operator delete, ::operator new[], ::operator delete[]也可以作为成员函数重载。
二十三、重载operator new,operator delete示例
- 使用全局作用域 :: 符号,可以强制采用全局函数。
- 编译器会在一个array的前头,添加一个counter记录array数量。
二十四、重载new(), delete()示例
- 分配内存,调用构造函数
- 程序发出异常,如果没有处理,程序就会退出。
- 我们可以重载class member operator new(),写出多好版本,前提是每一个版本的声明都必须有独特的参数列表,其中第一个参数必须是size_t,其余参数以new所指定的placement arguments为初值。出现于new(…)小括号内的便是所谓placement arguments。
- 我们也可以重载class member operator delete(),写出多好版本,但它们绝不会被delete调用。只有当new所调用ctor(构造函数)抛出exception(异常),才会调用这些重载版的operator delete()。它只可能这样被调用,主要用来归还未能完全创建成功的object所占用的memory。
二十五、basic_string使用new(extra)扩充申请量