- C++支持三种类型的成员函数:静态,非静态,和虚函数
- 静态成员函数不可能做到:直接存取非静态数据成员,被声明为const
4.1 Member的各种调用方式
非静态成员函数
- 成员函数被内化为非成员函数的形式
- 改写函数的signature以安插一个额外的参数到成员函数中,用以提供一个存取管道,使类对象得以将此函数调用。
- 将每一个对非静态成员函数的存取操作改为经由this指针来存取。
- 将成员函数重新写成一个外部函数。将函数名称经过mangling处理,使它在程序中成为一个独一无二的词汇。
名称的特殊处理
- 把参数和函数名称编码在一起,编译器于是在不同的编译模块之间达成了一种有限形式的类型检验。
- 编译错误消息用的是程序源码函数名称,然而连接器却不,它用的是经过mangled的内部名称。
虚拟成员函数
- 使用class scope operator 显示调用一个虚函数,其决议方式和非静态成员函数一样
- 经由一个类对象调用虚函数,这种操作应该总是被编译器对待一般非静态成员函数一样加以决议。
静态成员函数
- 主要特性是没有this指针
- 它不能直接存取其类中的非静态成员
- 他不能被声明为const,volatile,virtual
- 它不需要经由类对象才能调用.
- 如果取一个静态成员函数的地址,获得的将是其在内存中的位置,也就是其地址。地址的类型并不是一个指向类成员函数的指针,而是一个非成员函数的指针。
4.2 虚拟成员函数
- 多态指以一个public base class 的指针(或引用)寻址一个派生类对象
- 一个类若带有虚函数,他就支持多态,需要某些额外信息。
- 在实现上,首先我们可以在每一个多态的类对象身上增加两个members
- 一个字符串或数字,表示类的类型
- 一个指针,指向某表格,表格中持有程序的虚函数的执行期地址。 (vptrs)
- 每一个虚函数都被指派一个固定的索引值,这个索引在整个继承体系中保持与特定的虚函数的关系。
- 当一个类派生自一个带有虚函数的类时:
- 它可以继承基类所声明的虚函数的函数实例。
- 它可以使用自己的函数实例
- 他可以加入一个新的虚函数
多重继承下的虚函数
-
有三种情况,第二或后继的基类指针会影响对虚函数的支持
- 通过一个指向第二个基类的指针调用派生类虚函数
- 通过一个指向派生类的指针,调用第二个基类中一个继承而来的虚函数,在此情况下派生类指针必须再次调整,以至向第二个基类子对象。
- 允许一个虚函数的返回值类型有所变化,可能是基类类型,也可能是公共地派生类型。
-
经由指向第二个或后继之基类的指针来调用派生类虚函数,其所连带的必要的this指针调整操作必须在执行期完成。
-
thunk是一小段assembly代码:
- 以适当的offset调整this指针
- 跳到虚函数去。
-
Thunk技术允许虚表节点继续内涵一个简单指针,因此多重继承不需要任何空间上的负担。节点中的地址可以直接指向虚函数,也可以指向一个相关的thunk。
虚拟继承下的虚函数
- 不要在一个虚基类中声明非静态数据成员,如果这么做,你会距离复杂的深渊愈来愈近。