C++多态是如何实现的——一个简单明晰的例子告诉你!
C++多态是如何实现的——一个简单明晰的例子告诉你!
木兰宿莽 发表于1年前
C++多态是如何实现的——一个简单明晰的例子告诉你!
  • 发表于 1年前
  • 阅读 19
  • 收藏 2
  • 点赞 0
  • 评论 0

新睿云服务器60天免费使用,快来体验!>>>   

摘要: C++作为一种面向对象的编程语言,多态是应有之义。这里的多态不是单纯指C++的函数重载或者覆盖,而是指运行时绑定的动多态。C++的这种技术是通过虚函数表来实现的,虽然C++标准并没有强调一定要用这种做法,但各编译器厂商均采用这种做法。

先弄清楚几个概念:

1.C++多态依靠虚函数来实现;
2.凡是类中有带关键字virtual的函数均属于虚函数,如下:

class A
{
public:
   void f(){}  //--->普通成员函数
public:
   virtual void f1(void){...}  //---> 虚函数
   virtual void f2(void)=0;    //---> 纯虚函数
};

3.虚函数没有实体部分,即没有函数体而是等于零,则为纯虚函数。
4.拥有纯虚函数的类不能直接定义对象,如下报错:

int main()
{
  A a;//--->错误
return 0;
}

5.继承类需要定义纯虚函数实体才能定义对象,如下:

class B:public A
{
public:
   f2(void){
      //do something
   }
};
int main()
{
  B b;//--->正确
return 0;
}

6.虚函数一般是public成员函数,除非有特别的用处。

什么叫做虚函数表(vtables):
    虚函数表是一块连续的内存,每个内存单元中记录一个JMP指令的地址。
虚函数表属于类而不是具体对象,对不同的编译器其实现有所不同,比方
windows虚函数表放在常量段空间中,而linux/unix则放在只读数据段当中。
(引用别处说法,没有考证)
什么叫做虚函数指针(vptrs):
    每一个由有虚函数生成的对象包含指向虚函数的指针,注意不同对象的指

针地址不同,即指向不同(这里不同对象是指继承了具有虚函数基类的子类

所生成的对象),正是由于每个对象的虚函数指针指向的是自己对应类所实

现的函数,因此调用时对应的是子类对象的具体函数实现,从而完成了多态的
实现。

#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;
   }
 }
}

运行如下:

结语:
在大型的软件工程中,类的继承关系相当复杂庞大,在这样的情况下虚函数可以说
有了极大的用武之地了,一层层的继承关系,每个子类对虚函数都会做具体的实现
通过父类指针来调用这些函数可以在不同的代码段中实现不同的功能,极大的方便
了编程,而且让人感觉有点"智能"。
如shape调用Circle类的showShape函数来画一个圆,而调用Rectangle1类的showShape
函数来画一个长方形。这是一个简单的例子,形状有各种各样,但是shape指针可以分别
调用不同对象的showShape函数,加上不同的参数,便可以画出形形色色的图案。
试想,若没有这种多态机制,那么一定需要在具体的对象的指针各自调用各自的showShape
函数,这样即不利于编程,而且失去了父类指针统一调度各个类对象的函数的机制。

  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 33
博文 11
码字总数 9318
×
木兰宿莽
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: