资源描述:
《多态(polymorphism)的实现机制》由会员上传分享,免费在线阅读,更多相关内容在应用文档-天天文库。
1、多态(Polymorphism)的实现机制多态(Polymorphism)是面向对象的核心概念,本文以C++为例,讨论多态的具体实现。C++中多态可以分为基于继承和虚函数的动态多态以及基于模板的静态多态,如果没有特别指明,本文中出现的多态都是指前者,也就是基于继承和虚函数的动态多态。至于什么是多态,在面向对象中如何使用多态,使用多态的好处等等问题,如果大家感兴趣的话,可以找本面向对象的书来看看。为了方便说明,下面举一个简单的使用多态的例子(From[1]):classShape{protected:int
2、m_x;//Xcoordinateintm_y;//Ycoordinatepublic://PurevirtualfunctionfordrawingvirtualvoidDraw()=0;//AregularvirtualfunctionvirtualvoidMoveTo(intnewX,intnewY);//Regularmethod,notoverridable.voidErase();//ConstructorforShapeShape(intx,inty);//Virtualdestructor
3、forShapevirtual~Shape();};//CircleclassdeclarationclassCircle:publicShape{private:intm_radius;//Radiusofthecirclepublic://OverridetodrawacirclevirtualvoidDraw();//ConstructorforCircleCircle(intx,inty,intradius);//DestructorforCirclevirtual~Circle();};//Sh
4、apeconstructorimplementationShape::Shape(intx,inty){m_x=x;m_y=y;}//ShapedestructorimplementationShape::~Shape(){//...}//CircleconstructorimplementationCircle::Circle(intx,inty,intradius):Shape(x,y){m_radius=radius;}//CircledestructorimplementationCircle::
5、~Circle(){//...}//CircleoverrideofthepurevirtualDrawmethod.voidCircle::Draw(){glib_draw_circle(m_x,m_y,m_radius);}main(){//Defineacirclewithacenterat(50,100)andaradiusof25Shape*pShape=newCircle(50,100,25);//Defineacirclewithacenterat(5,5)andaradiusof2Circ
6、leaCircle(5,5,2);//VariousoperationsonaCircleviaaShapepointer//PolymorphismpShape->Draw();pShape->MoveTo(100,100);pShape->Erase();deletepShape;//InvokingtheDrawmethoddirectlyaCircle.Draw();}例子中使用到多态的代码以黑体标出了,它们一个很明显的特征就是通过一个基类的指针(或者引用)来调用不同子类的方法。那么,现在的问题是
7、,这个功能是怎样实现的呢?我们可以先来大概猜测一下:对于一般的方法调用,到了汇编代码这一层次的时候,一般都是使用Callfuncaddr这样的指令进行调用,其中funcaddr是要调用函数的地址。按理来说,当我使用指针pShape来调用Draw的时候,编译器应该将Shape::Draw的地址赋给funcaddr,然后Call指令就可以直接调用Shape::Draw了,这就跟用pShape来调用Shape::Erase一样。但是,运行结果却告诉我们,编译器赋给funcaddr的值却是Circle::Draw
8、de的值。这就说明,编译器在对待Draw方法和Erase方法时使用了双重标准。那么究竟是谁有这么大的法力,使编译器这个铁面无私的判官都要另眼相看呢?virtual!!Clever!!正是virtual这个关键字一手导演了这一出“乾坤大挪移”的好戏。说道这里,我们先要明确两个概念:静态绑定和动态绑定。1、静态绑定(staticbingding),也叫早期绑定,简单来说就是编译器在编译期间就明确知道所要调用的方法,并将该方法的地址