深度摸索C++对象模子(7)[VC/C++编程]
本文“深度摸索C++对象模子(7)[VC/C++编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
关于《深度摸索C++对象模子》停顿了半个月,本日持续啃这个骨头,我的学习进入了第四章,函数的语意学.先做个复习C++支持三种成员函数:静态、虚、和非静态.每一种函数的调用方法都差别,当然他们的作用也会有辨别,普通来说我们只要掌握按照我们的需求精确的利用这三种范例的成员函数便可以了,至于内部是若何运做的我们可以不知.但是《深度摸索C++对象模子》恰是让我们对这些不知道的东西举行深度摸索的一本书.通过前面的学习,我想我知道了一些从前不知道的东西,但是感受并没有提高多少,大概是我对此书的学习还逗留在一个对比菲薄的层次上吧.我想我应当会抽时间再看几遍.有些跑题了,因为雷神想阐明一下,这些笔记只是雷神看书是的一些设法的记录,假如你再看仅供参考,因为我本人好象也只摸索了不是很深的程度. 我们的在计划和利用类时最常用的就是非静态成员函数,利用成员函数是为了封装和躲藏我们的数据,我想这是成员函数和外部函数的最明显的辨别.但是他们的效率能否有差别呢?我们不会想为了保护我们的数据而利用成员函数,最后确招致效率降低的后果.让我们看看非静态成员函数在实际的履行时被编译器搞成了什么模样.
float magnitude3d(const Point3d *_this){…}
//这是一个外部函数,它有参数.表示它间接的获得坐标(Point3d)成员.
float Point3d::mangnitude3d() const {…}
//这是一个成员函数,它直接获得坐标(Point3d)的成员.
表面上看,仿佛成员函数的效率高很多,但实际上他们的效率真的想我们想象的那样吗?非也.实际上一个成员函数被内部转化成了外部函数.
1、 一个this指针被加入到成员函数的参数中,为的是可以使类的对象调用这个函数.
2、 将对全部非静态数据成员的存取操作改成由this来存取.
3、 对函数的名称举行重新的处理,使它成为程序中举世无双的.
这时后,经过以上的转换,成员函数已经成为了非成员函数.
float Point3d::mangnitude3d() const {…}//成员函数将被变成下面的模样
//伪码
mangnitude3d__7Point3dFv(register Point3d * const this)
{
return sqrt(this->_x * this->x+
this->_y * this->y+
this->_z * this->z);
}
调用此函数的操作也被转换
obj. mangnitude3d()
被转换成:
mangnitude3d__7Point3dFv(*obj);
怎么样看出来了吧,和我们开始声明的非成员函数没有辨别了.因此得出结论:两个铁球同时落地.
普通来说,一个成员的名称前面会被加上类的名称,形成唯一的命名.实际上在对成员名称做处理时,除了加上了类名,还会将参数的链表一并加上,这样才能保证后果是举世无双的.
我们在来看看静态成员函数.我们有这样的概念,成员函数的调用必须是用类的对象,象这样obj.fun();大概这样ptr->fun().但实际上,只有一个或多个静态数据成员被成员函数存取时才需求类的对象.类的对象供应一个指针this,用来将用到的非静态数据成员绑定到类对象对应的成员上.假如没有效到任何一个成员数据,就不需求用到this指针,也就没有必要通过类的对象来调用一个成员函数.并且我们还知道静态数据成员是在类之外的,可以被视做全局变量的,只不过它只在一个类的生命范围内可见.(参考前面的笔记).并且普通来说我们会将静态的数据成员声明为一个非Public.这样我们便必须供应一个或多个成员函数用来存取这个成员.固然我们可以不依靠类的对象存取静态数据成员,但是这个可以用来存取静态成员的函数确切必须绑定在类的对象上的.为了越发好的办理这个问题,cfront2.0引入了静态成员函数的概念.
静态成员函数是没有this指针的.因为它不需求通过类的对象来调用.并且它不能直接存取类中的非静态成员.并且不可以被声明为virtual,const,volatile.假如获得一个静态成员函数的地址,那么我们得到的是这个函数在内存中的位置.(非静态成员函数的地址我们得到的是一个指向这个类成员函数的指针,函数指针).可以看到由于静态成员函数没有this指针,和非成员函数非常的类似.
有了前面几章的底子,好象这些描写理解起来也不很吃力,并且我们的思绪可以随着书上所说的一路倾泻下来,这就是读书的爱好所在了,假如一本书读起来都想读第一章时那样吃力,我想我读不下去的大概性会很高.
持续我们的学习,下面书上开始将虚函数了.我们知道虚函数是C++的一个很重要的特点,面向对象的多态就是由虚函数实现的.多态的概念是一个用一个public base class的指针(大概引用),寻址出一个派生类对象.虚函数实现的模子是这样.每一个类都有一个虚函数表,它包含类中有作用的虚函数的地址,当类产生对象时会有一个指针,指向虚函数表.为了支持虚函数的机制,便有了“履行期多态”的情势.
下面这样.
我们可以定义一个基类的指针.
Point *ptr;
然后在履行期使他寻址出我们需求的对象.可以是
ptr =new Point2d;
还可以是
ptr=new Pont3d;
ptr这个指针负责使程序在任何地方都可以采取一组由基类派生的范例.这种多态情势是悲观的,因为它必须在编译期间完成.与之对应的是一种多态的主动情势,即在履行期完成用指针或引用查找我们的一个派生类的对象.
象下面这样:
ptr->z();
要想到达我们目的,这个函数z()应当是虚函数,并且还应当知道ptr所指的对象的真实范例,以便我们挑选z()的实体.以及z()实体的位置,以便我们可以调用它.这些工作编译器城市为我们做好,编译器是若何做的呢?
我们已知每一个类会有一个虚函数表,这个表中含有对应类的对象的全部虚函数实体的地址,并且大概会改写一个基类的虚函数实体.假如没有改写基类存在的虚函数实体,则会担当基类的函数实体,这还没完,还会有一个pure_virtual_called()的函数实体.每一个虚函数不管是担当的还是改写的,城市被指派一个固定的索引值,这个索引在整个担当体系中保持与特定的虚函数关联.
阐明:当没有改写基类的虚函数时,该函数的实体地址是被拷贝到派生类的虚函数表中的.
这样我们便实现了履行期的主动多态.这种情势的特点是,我们重新到尾都不知道ptr指针指向了那一个对象范例,基类?派生类1?派生类2?我们不知道,也不需求知道.我们只需求知道ptr指向的虚函数表.并且我们也不知道z()函数的实领会被调用,我们只知道z()函数的函数地址被放在虚函数表中的位置.
总结:在单一担当的体系中,虚函数机制是一种很有效率的机制.我们判断一个类能否支持多态,只需求看它有没有虚函数便可以了. 好了本日就到这里,雷神必须加快学习这本书的速度了,好象目前也可以快一些了.
以上是“深度摸索C++对象模子(7)[VC/C++编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |