zoukankan      html  css  js  c++  java
  • 对C++虚函数、虚函数表的简单理解

    一、虚函数的作用

    以一个通用的图形类来了解虚函数的定义,代码如下:

    #include "stdafx.h"
    #include <iostream>
    using namespace  std;
    
    class Graph
    {
    protected:
        double x;
        double y;
    public:
        Graph(double x,double y)
        {    
            this->x=x;
            this->y=y;
        }
        virtual void showArea()
        {
            cout<<"计算图形面积"<<endl;
        }
    };
    
    
    class Rectangle:public Graph
    {
    public:
        Rectangle(double x,double y):Graph(x,y){};
        virtual void showArea()
        {
            cout<<"矩形面积为:"<<x*y<<endl;
        }
    };
    
    
    class Triangle:public Graph
    {
    public:
        Triangle(double d,double h):Graph(d,h){};
        virtual void showArea()
        {
            cout<<"三角形面积为:"<<x*y*0.5<<endl;
        }
    };
    
    
    class Circle:public Graph
    {
    public:
        Circle(double r):Graph(r,r){};
        virtual void showArea()
        {
            cout<<"圆形面积为:"<<3.14*x*y<<endl;
        }
    };
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        Graph *graph;
    
        Rectangle rectangle(10,5);
        graph=&rectangle;
        graph->showArea();
    
        Triangle triangle(5,2.4);
        graph=&triangle;
        graph->showArea();
    
        Circle circle(2);
        graph=&circle;
        graph->showArea();    
        return 0;
    }

    输出如下,

    image

    该代码的作用是,设计不同的类去处理不同的图形,所有类继承于同一个Graph类。但是每个图形类都有一个相同的函数showArea。如果有需求是输出多个图形的面积,如果没有虚函数,就需要给每一种图形设计一个数组,然后每种图形分别处理。但是有了虚函数后,不管是什么图形,都只要设计一个Graph数组,然后调用每个成员的showArea函数即可。

    示例代码:

    Graph* gArray[3];
        gArray[0] = &rectangle;
        gArray[1] = &triangle;
        gArray[2] = &circle;
        for (int i = 0;i < 3;i++)
        {
            gArray[i]->showArea();
        }

    输出结果:

    image

    为什么会有这样的效果呢?原因就是有虚函数表。

    二、虚函数表

    调试上面的图形类代码,用IDE里的调试工具查看每个类对象;

    image

    每个对象(事实上,所有相同的类对象,都共用一个虚函数表)都有一个__vfptr成员数组,这个__vfptr就是虚函数表,偏移在基类和继承类中都是一样的,所以虚函数表可以在基类中访问到。

    但是仔细查看上面的图,可以看到,每个对象的虚函数表数组都是指向的不同的地址,分别指向自己类中的虚函数。

    所以如果指定graph->showArea()

    调用的函数是graph->__vfptr[0]()。

    这样就保证每个子类都调用的都是自己对应的虚函数了。

  • 相关阅读:
    Django 信号
    Python标准库12 数学与随机数 (math包,random包)
    利用python进行数据分析之数据聚合和分组运算
    利用python进行数据分析之绘图和可视化
    Django Aggregation聚合
    配置使用TargetFrameworks输出多版本类库
    WebApi 异常处理解决方案
    WebApi(6) 后台C#调用WebApi
    Target frameworks
    C#中lock死锁实例教程
  • 原文地址:https://www.cnblogs.com/Reyzal/p/5596555.html
Copyright © 2011-2022 走看看