侯捷C++面向对象高级编程(下)

一、导读

(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 成员模板

  1. 成员模板:模板里面再定义模板。
  2. 标准库里大量使用成员模板,用于改善类灵活性(up-cast)。

在这个例子中,成员模板的类型,需要满足一个条件:T1可以放进U1.first中,T2可以放进U1.second中,即U1.first的类是T1的基类,U1.second的类是T2的基类。

 

 

十、specialization  模板特化

(1)template <>中,<>里面没有类型的参数了,参数类型在后面绑定,即特化。

(2)template <class T>中,T的类型未被指定为特定类型,就是泛化。

编译器编译时,会确定模板是否存在特化,如果存在特化,优先使用特化代码。

 

 

十一、partial specialization 模板偏特化

  1. 模板的偏特化分为两种情况:个数的偏,范围的偏。
  2. 不管是模板特化,还是模板偏特化,都是将模板具体化的一些情况。
  3. class vector<bool, Allocator> { //…//};

这个偏特化的例子中,一个参数被绑定到bool类型,而另一个参数仍未绑定需要由用户指定。

  1. 范围偏特化:将原模板的类型T(泛指所有类型),范围缩小为指针类型(当然也可以是其他情况)。

在编译C<string*> obj2时,编译器将使用指针类型的模板。

 

 

十二、模板模板参数 

(1)模板的参数类型也是模板。

(2)只有在模板<>尖括号中,关键字typename与class是才通用的。

(3)带模板模板参数的模板,在第一次具体模板参数时,模板模板参数仍然未明确。

 

 

十三、关于C++标准库 

  1. 容器Container,就是数据结构:数组,列表,队列......
  2. 通过查看编译器宏 __cplusplus可以查看编译器支持的版本(199711L,201103L等)
  3. C++11 compiler support shootout: Visual Studio, GCC, Clang, Intel

网站http://cpprocks.com/c11-compiler-support-shootout-visual-studio-gcc-clang-intel/

 

 

十四、三个主题( 和C++11有关)

  1. variadic templates 数量不定的模板参数,即模板参数可变化。

例:template <typename T,typename...Types>

获取模板参数个数方法:sizeof...(Types)。

  1. auto 编译器可以推导变量的类型,就在变量前面加上auto,以代替变量类型。
  2. ranged-base for 即for循环的新形式:

decl:定义一个变量;coll:指定一个容器。

例子:

变量遍历可以传引用。

 

 

十五、reference

  1. 指针符号*是靠近类型,还是靠近变量合适?建议靠近类型。
  2. int& r =x; //r代表x, 逻辑上把r看作一个变量,但底层里,r的实现是指针。

r必须要有初值。

r不能再代表其他变量。

          编译器会处理对r进行处理,使其object和reference的大小相同,地址也相同(全都是假象),即:

      1. sizeof(r) == sizeof(x)
      2. &x == &r
  1. reference是一种漂亮的pointer。
  2. reference通常不用于声明变量,而用于参数类型和返回类型的描述。
  3. 返回值、reference不能用于区分函数签名。
  4. 函数const是函数签名的一部分。

 

 

 

-------------------下面讲的是对象模型Object Model,即class和class之间的关系-------------------

 

十六、复合&继承关系下的构造和析构 

 

 

十七、关于vptr和vtbl 

  1. vptr虚函数指针:指向虚函数列表(vtbl)头的指针。
  2. vtbl 虚表:存放vptr的列表。
  3. 每个有虚函数类的对象,都有一个vptr。
  4. 动态绑定:从对象指针,到vtbl虚表,到对象虚函数。
  5. 编译器将代码编译成动态绑定形式的条件:

通过指针(引用)调用;向上转型(子类到父类);调用的是虚函数。

  1. 多态、动态绑定、虚指针都是相同的东西。

 

 

十八、关于this指针

(1)Template Method(模板方法设计模式)。

(2)this可以理解为一个指针,也可以看作一个对象this object。

(3)在C++里,所有的非static成员函数,都有一个隐藏的参数 this。

十九、关于dynamic binding

动态绑定的发生,需要满足三个条件:1.指针(引用)调用;2.向上转型;3.调用虚函数。

 

-------------------------对象模型Object Model内容结束,以下是追加的课题 --------------------------

 

 

二十、谈谈const

  1. const是函数签名的一部分。
  2. COW: Copy On Write,需要修改数据时,单独拷贝一份数据进行修改。
  3. 当成员函数的const和non-const版本同时存在时,const object只会(只能)调用const版本,non-const object只会(只能)调用non-const版本。

 

 

二十一、关于new, delete

  1. 创建新对象时,先分配memory(内部调用malloc函数),再调用ctor(构造函数)。
  2. 释放新对象时,先调用dtor(析构函数),再释放memory(内部调用free函数)。
  3. array new一定要搭配array delete。

 

 

二十二、operator new,operator delete

  1. 重载 ::operator new, ::operator delete, ::operator new[], ::operator delete[],将接管全局的new和delete函数。
  2. 这些重载函数,是给编译器调用的:当重载这些函数之后,编译器将不会调用全局的new和delete函数。
  3. 这些重载函数,不可以被声明与一个namespace内。
  4. operator new, ::operator new[] 重载函数需要有一个大小参数。
  5. 小心,重载全局函数,影响将非常大。
  6. ::operator new, ::operator delete, ::operator new[], ::operator delete[]也可以作为成员函数重载。

 

 

二十三、重载operator new,operator delete示例

  1. 使用全局作用域 :: 符号,可以强制采用全局函数。
  2. 编译器会在一个array的前头,添加一个counter记录array数量。

 

 

二十四、重载new(), delete()示例

  1. 分配内存,调用构造函数
  2. 程序发出异常,如果没有处理,程序就会退出。
  3. 我们可以重载class member operator new(),写出多好版本,前提是每一个版本的声明都必须有独特的参数列表,其中第一个参数必须是size_t,其余参数以new所指定的placement arguments为初值。出现于new(…)小括号内的便是所谓placement arguments。
  4. 我们也可以重载class member operator delete(),写出多好版本,但它们绝不会被delete调用。只有当new所调用ctor(构造函数)抛出exception(异常),才会调用这些重载版的operator delete()。它只可能这样被调用,主要用来归还未能完全创建成功的object所占用的memory。

 

 

二十五、basic_string使用new(extra)扩充申请量

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值