天天看点

[读书笔记] 深入探索C++对象模型-第四章-Function语义学(上)

开始整理第四章的内容,关于函数的东西。

1. 静态成员函数不可以是const的,原因是因为this指针,详细参考:http://blog.csdn.net/beyongwang/article/details/52403697

2. 成员函数可以分成几类:

a. 非静态成员函数:此类函数会隐含一个this指针传入函数体,举个例子,对于如下函数:

float A::non_Static_Fun(){
    return m_a * m_a;
}
           

调用步骤如下:改写函数签名,添加this指针,对于const函数,会添加const A* this:

float A::non_Static_Fun(A* this){
    ...
}
           

将每一个非静态数据成员的存取改为由this指针来做:

float A::non_Static_Fun(A* this){
    return this->m_a * this->m_a;
}
           

将成员函数重新写成一个外部函数,对函数名字进行mangling处理,一般的处理方法是函数名称+参数数目+加参数类型,注意没有返回值,这也是为什么C++中,函数重载不允许通过返回值来区分,(添加extern C关键字可以阻止这种mangling),使其成为独一无二函数名字:

extern non_Static_Fun_7AFv(...);
           

相应的对于这个函数的调用操作也会被转换:

a.non_Static_Fun();
           

会转化为

non_Static_Fun_7AFv(&a);
           

指针调用:

pa->non_Static_Fun();
           

会转化成:

non_Static_Fun_7AFv(pa);
           

b. 虚拟成员函数:严格来说,虚函数也属于非静态成员函数,二者拥有部分相同的处理,但是由于跟普通的非静态成员函数处理上又有所不同,所以单独分成一类。例如,如果对于类A的一个虚成员函数v_Fun(void),这个调用pa->v_Fun(),可能会被转成为(* pa->vptr[1])(pa);其中,

    i. vptr是编译器产生的指向虚表的指针,对于所有含有或者继承有虚函数的类,都会存在,其名字可能也会被mangling化,因为同一个类中可能存在        多个此类指针。

    ii. 1是虚表槽的索引值,说明此函数位于虚表第二个函数槽中。

    iii. 第二个pa表示this指针。

注意,使用类对象调用虚函数和调用非虚函数的处理是一样的,并不会涉及虚表,例如:a.v_Fun()会转化为:v_Fun_7AFv(&a),跟上面调用非静态成员函数是一样的。这是因为类对象的类型是确定的,所以不必通过虚函数机制来决定被调用函数的地址。

c. 静态成员函数:

静态成员函数跟非静态成员函数的区别在于,前者没有this指针,因为从所属关系上来看,前者属于整个类,不存储特定的类实例状态,而后者可能因为不同的实例而产生不同的结果。例如,对于类A的一个静态成员函数void static_Fun(void),这个调用pa->static_Fun();以及这个调用:a.static_Fun();都会转化为一般的非成员函数调用:static_Fun_7ASFv();

几个静态函数的特征:

    i. 它不能直接存取所属类的非静态数据成员。

    ii. 它不能被声明为const, volatile或者virtual。

    iii. 它不需要通过类实例对象调用,A::static_Fun()。

取静态成员函数的地址: &A::static_Fun(),得到的是其在内存中的位置,也就是一个普通的函数指针:void (*)(),而不是指向类成员函数的指针void (A::*)()(关于指向类成员函数的指针,跟指向类成员变量的指针有点类似,之后会有整理)。

继续阅读