分享
 
 
 

C++对象模型之四 成员函数笔记

王朝c/c++·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

C++对象模型之四 成员函数笔记

成员函数的调用方式

非静态成员函数:C++设计准则之一就是非静态成员函数至少和一般的非成员函数一样的效率。

所以编译器内化成非成员函数,其步骤 1改写函数的原型以安插一个额外的参数到成员函数中,用以提供一个存取管道,使类对象得以调用该函数。 这个参数为 this 指针。

Point3d::Mangitude( Point3d *const this);

2 将每个对非静态数据成员的存取操作改为经由this指针来存取。

{ return sqr( this->_x * this->_x+ this->_y * this->_y+ this->_z * this->_z); }

3 将成员函数重新写成一个外部函数,对函数名称进行 mangling 处理。

Extern mangitude __7Point3dFv ( regiester Piont3d *const this)

虚成员函数 register float mag = Magnitude(); è register float mag = ( *this->vptr[2]) (this);

1 编译器生成vptr指针;2 虚函数表中的索引值;3就是this 指针

静态成员函数 obj.Magnitude(); ptr->Magnitude(); 都会转化成 Magnitude__7Point3dSFv();

虚成员函数

如果类中有虚函数,就会有虚函数表指针(vptr),表格的地址,大小和内容都是编译掌握住了。

执行时要做的是在特定的虚函数表槽激活虚函数。虚函数包括:1 派生类改写基类的虚函数,2 继承基类的虚函数,3 纯虚函数。

Class Pont

{

public:

virtual ~Point();

virtual Point& mult(float)=0;

float x() const {return _x;}

virtual float y() const { return 0;}

virtual float x() const { return 0;}

protecetd:

point (float x = 0.0);

float _x;

};

当一个类派生自Point时,会发生什么?

1 可能它继承基类所声明的虚函数的函数实体,正确地说是该函数实体的地址会被拷贝到派生类的虚函数表相对应的槽中

2 可能 它可以使用自己的函数实体,者表示它自己的函数实体地址必须放在对应的槽中

3 可能它可以加入一个新的虚函数表,这时候虚函数表的尺寸会增大一个槽,而新的函数实体地址会被放进该槽中。

多重继承下得虚函数

复杂度围绕在第二个及后继的基类身上,以及必须在执行时调整this指针

class Base1{

public: Base1();

virtual ~Base1();

virutal void speckclearly();

virutal Base1 *clone() const;

protected: float data_Base1;

};

class Base2{

public: Base1();

virtual ~Base2();

virutal void mumble();

virutal Base1 *clone() const;

protected: float data_Base2;

};

class Derived :public Base1,public Base2

{

public:

Derived();

Virtual ~Derived();

Virtual Derived *clone() const;

Protected : float data_Derived;

};

Base2 *pbase2 = new derived;

è 调整: Derived *temp = new Derived; Base2 *pbase2 = temp ? temp + sizeof(Base1):0;

当第二个基类的指针调用派生类的虚函数时,必须在执行中完成调整。也就是offset

this+=sizeof(base1);

Derived::~Derived(this);

虚函数在虚继承下

class Point2d{

public: Point2d( float = 0.0, float = 0.0);

virtual ~Point2d();

virtual void mumble();

virtual float z();

protected: float _x , _y ;

};

class Point3d :public virtual Point2d{

public: point3d (float = 0.0 , float = 0.0 );

~Point3d();

float z();

protected: float _z;

};

由于Point2d和Point3d的对象不再相符,两者之间的转换也就需要调整this指针.

函数效率

未优化

优化

内联成员

4.70

0.08

友元函数

6.13

4.43

静态成员

6.13

4.43

非静态成员

6.13

4.43

虚函数

6.90

4.76

虚函数多继承

7.06

4.90

虚函数虚继承

7.07

5.44

指向成员函数的指针

取个非静态成员函数的地址,如果它不是虚函数,则得到的是在内存中真正的地址。不过需要绑定在某个对象地址上。使用一个成员函数指针,如果并不用于虚函数,多重继承,虚继承等情况不会比一般的指针成本高。

指向虚函数的指针

float (Point:: *pmf) () = &Point::z; //取虚函数的地址得到是在虚函数表的索引值

( * ptr->vptr[ (int) pmf ] ) (ptr); //通过调用会被内部转化为一个编译时期的式子

区分PMF调用的是虚函数还是非虚函数方法:

( ( ( int ) pmf ) & ~127 ) ? (* pmf ) ( ptr ) : ( *ptrèvptr[ ( int) pmf ] ( ptr ) );

指向多重继承和虚继承的指针

采用结构体

struct _mptr

{

int delta; //表示this指针的offset

int index;

union {

ptrtofunc faddr;

int v_offset; //虚函数在虚函数表的索引

};

};

( ptr-> *pmf) (); 会变成 (pmf.index < 0 )? ( pmf.faddr ) (ptr ): ( ptr->vptr[ pmf.index ]( ptr ) );

指向成员函数指针的效率

未优化

优化

非成员函数指针

6.12

4.30

成员函数指针

6.38

4.30

多重继承非虚函数指针

6.32

4.30

虚继承非虚函数指针

6.84

4.70

虚函数指针

7.39

4.70

多重继承虚函数指针

8.72

5.90

虚继承虚函数指针

8.80

5.84

内联函数

一般而言处理内联函数有两个阶段

1 分析函数定义,以决定函数的内联的本资。如果判断其不可内联就会转化成静态函数。

2 内联函数的展开是在调用点上,这样会带来参数求值和临时对象管理。

形式参数

inline int min( int I,int j) { return I<j ? I:j ;}

main()

{

int minval ;

int val1=1024;

int val2=2048;

minval = min (val1,val2);

minval = min (1024,2048);

minval = min (foo(),bar()+1);

}

第一调用的 minval = val1 <val2 ? val1 : val2;

第二调用的 minval = 1024;

第三调用的 int t1; int t2; minval = (t1 =foo() ),(t2 = bar()+1) t1<t2 ? t1: t2; / / 临时对象

在inline扩展时,每一个形式参数都会被实际参数取代。如果会导致对于实际参数多次求值就会引入临时对象。

局部变量

inline int min(int i,int j)

{

int minval = i < j ? i : j ;

return minval ;

}

main()

{ int loval _var,minval;

minval = min (val1,val2);

}

就会被扩展为:

{ int local _var, minval ;

int__min_lv_minval;

minval = (__min_lv_minval = val1 < val2 ? val1: val2), __min_lv_minval;

}

一般而言,内联函数中的每个局部变量都必须被放在函数调用的一个封闭区间中,拥有独一无二的名称。

如果内联函数以单一表达式扩展多次,那么每次都需要一组局部变量。以分离多个式子被扩展多次,那么只需要一组局部变量,就可以重复使用了。

作者名:曾凡坤, 又名曾牧暗鲨,网名:大白鲨 2003-8-3

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有