先弄清楚几个概念:linux
1.C++多态依靠虚函数来实现;
2.凡是类中有带关键字virtual的函数均属于虚函数,以下:ios
class A { public: void f(){} //--->普通成员函数 public: virtual void f1(void){...} //---> 虚函数 virtual void f2(void)=0; //---> 纯虚函数 };
3.虚函数没有实体部分,即没有函数体而是等于零,则为纯虚函数。
4.拥有纯虚函数的类不能直接定义对象,以下报错:编程
int main() { A a;//--->错误 return 0; }
5.继承类须要定义纯虚函数实体才能定义对象,以下:windows
class B:public A { public: f2(void){ //do something } }; int main() { B b;//--->正确 return 0; }
6.虚函数通常是public成员函数,除非有特别的用处。函数
什么叫作虚函数表(vtables):
虚函数表是一块连续的内存,每一个内存单元中记录一个JMP指令的地址。
虚函数表属于类而不是具体对象,对不一样的编译器其实现有所不一样,比方
windows虚函数表放在常量段空间中,而linux/unix则放在只读数据段当中。
(引用别处说法,没有考证)
什么叫作虚函数指针(vptrs):
每个由有虚函数生成的对象包含指向虚函数的指针,注意不一样对象的指this
针地址不一样,即指向不一样(这里不一样对象是指继承了具备虚函数基类的子类spa
所生成的对象),正是因为每一个对象的虚函数指针指向的是本身对应类所实unix
现的函数,所以调用时对应的是子类对象的具体函数实现,从而完成了多态的
实现。指针
#include "stdafx.h" #include<iostream> #include<cmath> #include<ctime> #include<windows.h> using namespace std; enum Color { Red, Black, Yellow, Orange, Brown, White }; class Shape { protected: double xPos; double yPos; Color color; public: Shape(double x=0.0f,double y=0.0f,Color c=White):xPos(x),yPos(y),color(c){} ~Shape(){} protected: public: virtual void setColor(Color)=0; virtual Color getColor()=0; virtual bool drawShape(double,double)=0; virtual void setPosition(double,double)=0; virtual void movePosition(double,double)=0; virtual void erase()=0; virtual void showShape()=0; }; class Circle:public Shape { private: double radius; public: Circle(double r=1.0f):radius(r),Shape(){} ~Circle(){} public: double getRadius(){ return radius; } void setPosition(double x=0.0f,double y=0.0f){ xPos=x; yPos=y; } bool drawShape(double x=0.0f,double y=0.0f){return true;} void movePosition(double x=0.0f,double y=0.0f){} void erase(){} void showShape(){ //画一个半径为radius的圆 for(double yv=this->radius;yv>=-this->radius;yv-=0.1f){ for(double xv=this->radius;xv>=-this->radius;xv-=0.05f){ if(sqrt(pow(xv,2)+pow(yv,2))<=this->radius){ cout<<"*"; } else{ cout<<" "; } } endl(cout); } } Color getColor(){ return Shape::color; } void setColor(Color c=Red){ } }; class Rectangle1:public Shape { private: double length; double width; public: Rectangle1(double l=2.0f,double w=1.0f,double x=0.0f,double y=0.0f):length(l),width(w),Shape(x,y){} ~Rectangle1(){} public: void setPosition(double x=0.0f,double y=0.0f){ xPos=x; yPos=y; } bool drawShape(double x=0.0f,double y=0.0f){ return true;} void movePosition(double x=0.0f,double y=0.0f){ xPos+=x; yPos+=y; } void erase(){} void showShape(){ //画一个长宽为xv和yv的长方形 for(double yv=0.0f;yv<=yPos+width;yv+=0.05f){ for(double xv=0.0f;xv<=xPos+length;xv+=0.05f){ if(yv>=yPos&&xv>=xPos)cout<<"*"; else cout<<" "; } endl(cout); } } void setColor(Color c=Red){ } Color getColor(){ return Shape::color; } }; int _tmain(int argc, _TCHAR* argv[]) { Shape* shape; while(true){ for(int i=1;i<=3;i++){ shape=new Circle(i*0.5f); shape->showShape(); //经过虚函数表调用Circle类的showShape函数 Sleep(500); delete shape; shape=new Rectangle1(0.3f*i,0.3f*i,0.3f*i,0.3f*i); shape->showShape(); //经过虚函数表调用Rectangle1类的showShape函数 delete shape; } } }
运行以下:code
结语: 在大型的软件工程中,类的继承关系至关复杂庞大,在这样的状况下虚函数能够说 有了极大的用武之地了,一层层的继承关系,每一个子类对虚函数都会作具体的实现 经过父类指针来调用这些函数能够在不一样的代码段中实现不一样的功能,极大的方便 了编程,并且让人感受有点"智能"。 如shape调用Circle类的showShape函数来画一个圆,而调用Rectangle1类的showShape 函数来画一个长方形。这是一个简单的例子,形状有各类各样,可是shape指针能够分别 调用不一样对象的showShape函数,加上不一样的参数,即可以画出形形色色的图案。 试想,若没有这种多态机制,那么必定须要在具体的对象的指针各自调用各自的showShape 函数,这样即不利于编程,并且失去了父类指针统一调度各个类对象的函数的机制。