C++ 中的virtual关键词

动态绑定

所谓动态绑定,我的理解就是一个函数在调用之前无法得知参数的具体类型(基类还是派生类)。C++ Primer上描述了两种动态绑定的情况:

要触发动态绑定,必须满足两个条件:一、指定为虚函数的成员函数。二、通过基类类型的引用或指针进行函数调用。

基类和派生类的关系

派生类是由基类派生而来,其包含基类的所有内容,并进行扩展和修改(覆盖)。比如对基类Base和派生类Derived来说,我们可以说Derived就是Base类型的,也就是说在使用Base类型做形参的函数调用中都可以使用Derived类型。这个是安全的,因为派生类本身就包含了基类子对象。

virtual关键词

上面提到动态绑定的两个条件,第一条要求成员函数为虚函数。虚函数使用virtual关键词进行声明。现在看一个例子:

void printClass(const Base &item)
{
cout << item.size()<< item.price()<<endl;
}

其中,size()函数在基类Base中声明为普通成员函数,而price()函数在基类Base中声明为虚成员函数。类Derived是Base类的派生类,且在Derived类中对price()类进行了覆盖。对于以下调用:

Base base;
Derived derived;
printClass(base);
printClass(derived);

由于printClass的参数是基类类型,而size()函数是普通成员函数,因此两个函数调用时都调用了基类(派生类中包含基类的子对象)的size(),即Base::size()。而对于虚函数price()来说,第一个调用调用的是Base::price(),第二个调用的是Derived::price()。

C++ 中的virtual关键词的更多相关文章

  1. 【09】绝不在构造和析构过程中调用virtual方法

    1.绝不在构造和析构过程中调用virtual方法,为啥? 原因很简单,对于前者,这种情况下,子类专有成分还没有构造,对于后者,子类专有成分已经销毁,因此调用的并不是子类重写的方法,这不是程序员所期望的 ...

  2. C#中的Virtual

    在 C# 中,派生类可以包含与基类方法同名的方法. 基类方法必须定义为 virtual. 如果派生类中的方法前面没有 new 或 override 关键字,则编译器将发出警告,该方法将有如存在 new ...

  3. NO.8:绝不在构造或者析构过程中调用virtual函数

    在构造和析构执行期间不要调用virtual函数,因为这类调用从不会下降至derived class(比起当前执行构造函数和析构函数) 如果在base class 构造函数或者析构函数调用virtual ...

  4. VMware与Cisco DRAC中的virtual disk的对应关系

    笔者面临的问题如下: 笔者有一台Cisco C240的服务器, 其中有十块容量一样大的SAS的local disk, 一块SSD. 其中的两块SAS盘组成了一个RAID 1的virtual drive ...

  5. Effective C++ .09 不在构造和析构过程中调用virtual函数

    看过C++对象模型的话就可以知道,在构造基类时,完整的vtable没有建立起来(表项没有被相应的子类函数替换),因而无法调用到子类的函数(即构造函数中的virtual函数是本类里的方法,不是virtu ...

  6. java并发中的Synchronized关键词

    文章目录 为什么要同步 Synchronized关键词 Synchronized Instance Methods Synchronized Static Methods Synchronized B ...

  7. C#中的Virtual、Override和new关键词理解

    来源:http://blog.csdn.net/jackiezhw/article/details/2673992 在 C# 中,派生类可以包含与基类方法同名的方法. 基类方法必须定义为 virtua ...

  8. 该不该在C#中使用var关键词

    作为一个并不勤快的程序猿,在项目开发过程中总是想尽办法少写代码,对var关键词的使用自然不会放过,几乎在每个能使用var的地方都用了var,对此,很多朋友同事给出了不同的建议,觉得能不使用var关键词 ...

  9. 绝不在构造和析构函数中调用 virtual 函数

    看下面的这段代码,问 print调用的是基类还是派生类的版本? 答案是 基类... 可能大家会很惊讶,print不是virtual function 吗?为什么不是调用派生类的版本呢? 首先,当定义一 ...

随机推荐

  1. js date string parse

    function dateParse(dStr){ //var dStr = '2016-1-26 0:7:14'; var d = dStr.split(' ')[0].split('-'); va ...

  2. oracle创建自增长列

    --创建一个新表 /*create table students(stu_id number,stu_name varchar2(20),stu_email varchar2(40),primary ...

  3. UITextfiled子视图被剪切

    一般情况下,如果在view1上面添加了view2,但是view2超出了view1,也会在屏幕上面显示超出的部分 例如: UIButton *button =[[UIButton alloc]initW ...

  4. 如何加入自定义WebControl

    http://www.screencast.com/users/Dennis.Garavsky/folders/Default/media/c75b4ec6-1641-4f82-936e-39360d ...

  5. Number

    https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/parseInt 概述 parseIn ...

  6. Ext_两种处理服务器端返回值的方式

    1.Form表单提交返回值处理 //提交基本信息表单  f.form.submit({      clientValidation:true,      //表单提交后台处理地址      url:' ...

  7. spring中propertyplaceholderconfigurer简介

    Spring的框架中为您提供了一个 BeanFactoryPostProcessor 的实作类别: org.springframework.beans.factory.config.PropertyP ...

  8. NotePad++ 列模式(在多行开头统一添加相同内容)

    ==> 按住Alt键不放,用鼠标左键从第一行的开头处按住向下拉,直到所有行 松开Alt键和鼠标左键,你会发现光标变成了一条跨越所有行的竖线 ==> 如果不想使用鼠标操作,可以使用 Alt+ ...

  9. vim复制多行<转>

    比如我要复制从第1行到第5行的数据,复制到第9行 光标移到第5行任意位置,输入ma光标移到第1行任意位置,输入y'a(这一定要打这个“'”单引号,否则就进入“INSERT”状态了光标移到需要复制的行, ...

  10. 哈希表(Hash)的应用

    $hs=@() #定义数组 $hs=@{} #定义Hash表,使用哈希表的键可以直接访问对应的值,如 $hs["王五"] 或者 $hs.王五 的值为 75 $hs=@''@ #定义 ...