文档章节

C++多态是如何实现的——一个简单明晰的例子告诉你!

木兰宿莽
 木兰宿莽
发布于 2016/11/17 22:24
字数 1210
阅读 22
收藏 2

先弄清楚几个概念:

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
函数,这样即不利于编程,而且失去了父类指针统一调度各个类对象的函数的机制。

© 著作权归作者所有

共有 人打赏支持
木兰宿莽
粉丝 35
博文 12
码字总数 8250
作品 0
崇明
程序员
私信 提问
C中的继承和多态

2010-09-23 00:27 by 吴秦,19167 阅读,23 评论,收藏,编辑 1、引言 继承和多态是面向对象语言最强大的功能。有了继承和多态,我们可以完成代码重用。在C中有许多技巧可以实现多态。本文的目的...

老朱教授
2017/11/26
0
0
cocos2d-x lua代码臃肿,有没有解决方案?客户端动态更新其他好建议吗?

近期开始学习并使用lua。软件分层的思想全世界可以用。但是纯lua的开发模式实现却很难使用多态和封装,也许是我水平低。面临的实际问题却是代码臃肿,不断的循环遍历(我在做解析文本)。我有...

王敬哲
2014/06/10
1K
4
绕开“陷阱“,阿里专家带你深入理解C++对象模型的特殊之处

摘要:本文介绍了C++对象模型的特殊之处,包括与C兼容的朴素模型,以及能支持多态的虚表模型,同时还带大家了解了构造函数与析构函数相关的一些特性与陷阱。这些内容能够帮助大家更好地学习和...

nirvanalucky
04/25
0
0
C语言/C++编程学习—神奇设计模式代码之群星

C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到...

小辰带你看世界
03/26
0
0
sizeof(空类或空结构体)

某童靴前天去理想国际某公司面试,回来在宿舍讨论了这样一道题: VC++里,有一个空类,没有声明任何成员变量或函数,请问此空类占多大字节空间? A、 0 B、 1 C、 4 D、8 当时考虑了32bit和6...

长平狐
2013/01/06
68
1

没有更多内容

加载失败,请刷新页面

加载更多

Sping之项目中pofile的应用

工程中,我们必须要面对的一件事就是, 开发环境中使用的数据库连接地址等与生产上的不同, 如果上线, 那么我们是否还要手动修改这些地址么, 这样做有很多弊端, 不方便, 这时我们就可以使用spr...

克虏伯
17分钟前
0
0
Linux中安装MySQL

Linux中安装MySQL 一、准备工作 此处准备的操作系统位CentOS 7。 MySQL安装包: MySQL-server-5.6.29-1.linux_glibc2.5.x86_64.rpm MySQL-client-5.6.29-1.linux_glibc2.5.x86_64.rpm 将准备......

星汉
22分钟前
0
0
深入理解Hadoop之HDFS架构

Hadoop分布式文件系统(HDFS)是一种分布式文件系统。它与现有的分布式文件系统有许多相似之处。但是,与其他分布式文件系统的差异是值得我们注意的: HDFS具有高度容错能力,旨在部署在低成...

架构师springboot
26分钟前
1
0
MaxCompute表设计最佳实践

MaxCompute表设计最佳实践 产生大量小文件的操作 MaxCompute表的小文件会影响存储和计算性能,因此我们先介绍下什么样的操作会产生大量小文件,从 而在做表设计的时候考虑避开此类操作。 使用...

阿里云官方博客
26分钟前
0
0
云上领跑,快人一步:华为云抢先发布Redis5.0

12月17日,华为云在DCS2.0的基础上,快人一步,抢先推出了新的Redis 5.0产品,这是一个崭新的突破。目前国内在缓存领域的发展普遍停留在Redis4.0阶段,华为云率先发布了Redis5.0,全面展现了...

中间件小哥
26分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部