member functions的调用方式
- c++支持三种类型的member functions:static、nonstatic、virtual,且每一种调用方式不尽相同
nonstatic member functions
- nonstatic member function至少和nonmember function有着相同的效率
? 现有如下函数调用:
float do(const A *_this) {...}
float A::do() const {...}
//第一个函数转换
float do(const A *_this)
{
return sqrt(
_this->x * _this->x + _this->y * _this->y + _this->z * _this->z
)
};
//第二个nonstatic member function转换成上面相同的形式nonmember function
-
nonstatic member function转化为 nonmember function步骤:
-
改写函数原型以安插一个额外参数到member function,将提供class object存取渠道,此参数也就是this指针。若member function为const,this也需加个const
float do(const A* const _this)
-
将每个对nonstatic data member的存取操作改为this指针
_this->x * _this->x + _this->y * _this->y + _this->z * _this->z
-
将member function经过mangling处理重新写为一个外部函数,且名称是独一无二的
extern do_7AFv( A* const this );
-
-
一般而言,data member的名称前会加上class名称,形成独一无二的命名;而member function则还需加上参数链表
class B { public: int val; ... }; //对val进行name mangling val_3; ----------------------- class C { public: void x(float newX); float x(); } //member function进行name mangling void x__5CFf(float newX); float x__5CFv();
virtual member functions
? 现有如下代码:
class A
{
virtual A do1() const;
virtual float do2() const;
}
A a;
A* pt = &a;
pt->do1();
//转化
( *pt->vptr[1] )(pt);
float d = do2();
//转化
float d = ( *this->vptr[2] )( this );
a.do1();
//转化
( *a.vptr[1] )( &a );
? ( * pt -> vptr [1] )( pt )其中:1为virtual table slot的索引值,关联到virtual member function,也就是do1()
? ( *a.vptr[1] )( &a ) 没有必要,应该这样调用:A::do1()
-
经由class object调用virtual function优化跟nonstatic member function一样
-
为支持virtual function机制,需要能对多态对象进行执行期类型判断,将必要信息加在指针或引用上。而必要信息则有:
- 指针或引用指向的对象的地址
- 对象类型的结构的地址
-
多态表示用一个public base class的指针或引用寻址一个derived class object
Point* ptr; ptr = new Point2d;
-
当前ptr被称为消极的多态形式,可以在编译时期完成(virtual base class除外);当ptr指出的具体对象被使用时才是积极的
ptr->z();
-
class是否支持多态,唯一方法是看其是否有virtual function
-
-
实现多态。我们需要在每个class object上增加两个members:
- 一个字符串或数字,表示class类型
- 一个指针,指向一表格,表格中含有virtual functions执行期地址
-
随后只需两步即可找到其地址:
- 每个class object安插一个由编译器生成的指针,该指针指向表格
- 每个virtual function被指派一个表格索引值
-
一个class只有一个virtual table,每个table内含对应的class object中的active virtual functions实例地址。而active virtual functions又包括:
- 这一class定义的函数实例
- 继承自base class的函数实例
- 一个pure virtual called函数
-
对于多重继承,销毁对象时若调用delete需要指向derived class object的起始处,但因为指针或引用真正所指的对象在执行期才可以确定,所以offset无法在编译期求得。针对多重继承这种情况,derived class需要内含n-1个额外的virtual tables(n表示其上一层base classes个数)。那么如何支持一个class拥有多个virtual tables呢?只需将每一个tables以外部对象的形式产出,并赋予独一无二的名称
-
不要在virtual base class中声明nonstatic data members
static member function
- static member function特性:
- 没有this指针,成为一个callback函数
- 不可直接存取class中的nonstatic members
- 不可被声明为const、volatile、virtual
- 不需要经由class object调用
- static member function同样也有name mangling
- 对static member function取地址,得到的是内存中的地址;由于没有this指针,static member function地址类型是一个nonmember函数指针
指向member functions 的指针
-
指向member function的指针和指向member selection operator的指针,其作用是作为this指针的空间保留者。这也说明了为什么static member function的指针类型是函数指针,毕竟其没有this指针
-
使用member function指针,若不用于virtual function、多重virtual继承、virtual base class,其成本跟用nomember function指针差不多
-
virtual member function的地址在编译期是未知的,我们所能知道的仅是virtual function在其相关之virtual table的索引值
inline functions
-
inline关键词只是一个请求,若此请求被编译期接受,编译期则