0x01:前言

虚函数是C++里最重要的概念之一,并且是判定C++是否入门的一个热门问题。今天这篇文章简单谈谈虚函数。

0x02:虚函数简介

虚函数可以被子类实现函数所覆盖。

virtual是关键字,被定义为virtual的函数才可以被子类覆盖。

虚函数的调用是通过虚函数指针调用。

0x03:虚函数原理

下面展示的代码皆为伪码,主要为说明虚函数编译和调用过程。

class Base
{
public:
virtual void Play();
virtual void Move();
virtual void Attack();
void EndGame();
};

在这里Base类在编译时会生成虚函数表: FunctionPtr* Base::__vtable[3] = {&Base::Play(), &Base::Move(), &Base::Attack()}

在生成Base对象时,会生成虚函数指针 FunctionPtr* Base::__vptr;

class Base
{
public:
Base():__vptr(__vtable[0])
{
}
FunctionPtr* __vptr;
};

假设如下场景:

Base b;
b.Move(); // b.__vptr[1]();

如果通过继承,变的只是虚函数表。

class Derived : public Base
{
public:
void Move() override;
}

此时虚函数表:FunctionPtr* __vtable[3] = {&Base::Play(), &Derived::Move(), &Base::Attack()}

0x04:虚函数性能

对于调用消耗是非常小的,不过对于效率要求非常严苛的使用场景另当别论。效率更多是转化成经济效益计算。提高效率,开发难度和时间本来是此起彼消的。

参考:https://isocpp.org/wiki/faq/virtual-functions

C++ 虚函数畅谈的更多相关文章

  1. C++虚函数和函数指针一起使用

    C++虚函数和函数指针一起使用,写起来有点麻烦. 下面贴出一份示例代码,可作参考.(需要支持C++11编译) #include <stdio.h> #include <list> ...

  2. 匹夫细说C#:从园友留言到动手实现C#虚函数机制

    前言 上一篇文章匹夫通过CIL代码简析了一下C#函数调用的话题.虽然点击进来的童鞋并不如匹夫预料的那么多,但也还是有一些挺有质量的来自园友的回复.这不,就有一个园友提出了这样一个代码,这段代码如果被编 ...

  3. 【C++】多态性(函数重载与虚函数)

    多态性就是同一符号或名字在不同情况下具有不同解释的现象.多态性有两种表现形式: 编译时多态性:同一对象收到相同的消息却产生不同的函数调用,一般通过函数重载来实现,在编译时就实现了绑定,属于静态绑定. ...

  4. 虚函数的使用 以及虚函数与重载的关系, 空虚函数的作用,纯虚函数->抽象类,基类虚析构函数使释放对象更彻底

    为了访问公有派生类的特定成员,可以通过讲基类指针显示转换为派生类指针. 也可以将基类的非静态成员函数定义为虚函数(在函数前加上virtual) #include<iostream> usi ...

  5. C++ 系列:虚函数

    Copyright © 1900-2016, NORYES, All Rights Reserved. http://www.cnblogs.com/noryes/ 欢迎转载,请保留此版权声明. -- ...

  6. EC笔记,第二部分:9.不在构造、析构函数中调用虚函数

    9.不在构造.析构函数中调用虚函数 1.在构造函数和析构函数中调用虚函数会产生什么结果呢? #; } 上述程序会产生什么样的输出呢? 你一定会以为会输出: cls2 make cls2 delete ...

  7. C++构造函数中不能调用虚函数

    在构造函数中调用虚函数,并不会产生多态的效果,就跟普通函数一样. c++ primer 第四版中497页15.4.5构造函数和析构中的虚函数讲到,如果在构造函数或析构函数中调用虚函数,则运行的是为构造 ...

  8. C#虚函数和接口的区别

    接口只能声明不能实现,虚函数可以. 接口:对外提供可以访问的函数叫接口.虚函数不需要被强制重写,其本身含有实现部分. 抽象类:指派了派生类必须实现的函数(纯虚函数),不然编译不通过. 虚函数的限制:  ...

  9. c++ 虚函数

    class A { public: virtual void f();//希望派生类重写 void fun();//绝大多数情况下不要重新定义基类的非虚函数,那样会打破公有继承Is-A的关系,而且行为 ...

随机推荐

  1. Xamarin Android提示内存溢出错误

    Xamarin Android提示内存溢出错误 错误信息:java.lang.OutOfMemoryError, Consider increasing the value of $(JavaMaxi ...

  2. div垂直居中 css div盒子上下垂直居中

    div垂直居中 css div盒子上下垂直居中,让DIV盒子在任何浏览器中任何分辨率的显示屏浏览器中处于水平居中和上下垂直居中. div垂直居中常用于单个盒子,如一个页面里只有一个登录布局,使用div ...

  3. java中的String设计原理

    首先,必须强调一点:String Pool不是在堆区,也不是在栈区,而是存在于方法区(Method Area) 解析: String Pool是常量池(Constant  Pool)中的一块. 我们知 ...

  4. SplendidCRM 如何添加及使用中文语言包

    SplendidCRM 功能很强大,也支持多国语言,但关于中文语言安装的介绍在网上一直都找到,自已摸索了一下,成功使SplendidCRM应用中文,以下是安装方法. 版本号:SplendidCRM 7 ...

  5. cocosjs 触摸

    /** * Created by sun on 15/11/24. */ var Piece = cc.Sprite.extend({ ctor:function (num) { this._supe ...

  6. COJ983 WZJ的数据结构(负十七)

    显然是动态树裸题:O(mlogn) #include<cstdio> #include<cstring> #include<algorithm> #include& ...

  7. linux 好用的程序

    来自   http://www.cnblogs.com/skyseraph/archive/2010/10/30/1865280.html * Shell: bash.我使用 bash 的 vi 命令 ...

  8. [百科]sys/types.h

    sys/types.h中文名称为基本系统数据类型.在应用程序源文件中包含 <sys/types.h> 以访问 _LP64 和 _ILP32 的定义.此头文件还包含适当时应使用的多个基本派生 ...

  9. 发生了COMException 异常来自 HRESULT:0x80040228

    异常信息: 发生了COMException 异常来自 HRESULT:0x80040228 原因解决方法:窗体中忘记放LicenseControl控件.,加上LicenseControl即可

  10. hdu City Game

    做这题之前建议做一下hdu1506题,两道题是极度相似的题,不同的是这个要处理的是m行,所以可以用一个dp[][]数组存储矩形的高度,之后就变成hdu1506了. 例如测试样例: 0 1 1 1 1 ...