虚函数是C++中实现多态的一种方法,父类A的一个函数声明为虚函数,在子类B中覆盖定义之后,当在调用的时候使用A*a=new B(),此时调用对应的那个虚函数的名字,则会执行B中的函数。当父类中没有定义虚函数的实体时候,virtual void foo()=0;这个函数就是一个纯虚函数,对应的父类就是抽象类,则这个抽象类不能被实例化,只能由子类派生实例化。

每个含有虚函数的对象都有一个虚指针,这个虚指针和这个对象的基地址是一样的,即一个对象的第一块内存单元存储的一定这个类对象的虚指针。

普通继承中,B对象中只有一个虚指针,这个指针指向A、B中的所有虚函数存在的虚表;对于虚拟继承来讲,在B的对象中会有两个虚指针,一个是仅仅只有A对象的虚表,另一个指针是A、B所有的虚函数虚表指针。当然,包含A、B所共有的虚函数的虚表指针是和B在同一个基地址上的,即B对象的第一个单元的指针即是虚表指针。另外还需要注意的是当B覆盖了A中定义的虚函数之后,B对象中的仅仅只有A的虚函数的那个虚指针所在的虚表项目会做调整,里面的函数指针指向的是覆盖后的函数(B中的函数)。

还有一个地方需要注意,就是虚函数和重载函数的问题。虚函数重写的时候是允许返回值有差异的,但是对参数的要求很严格。遵循以下规则:

a)      参数必须类型一样,即使有继承关系也不行,Base* Base::copy(Base*); Base* Derived::copy(Derived*),这样是不能够达到虚函数的效果的;

b)     参数类型一样,而且也允许在父类中有默认值,则子类继承这个默认值,即ostream& Base::print(int,ostream&=cout); ostream& Derived::print(int,ostream&);这样的写法是允许的,而且这个默认值写在子类和父类都是可以的,若写在父类中,使用子类调用的时候默认值必须写上;

c)      对于函数const属性修饰符,若一个加一个没有加,则看成是重载函数而不是重写;

d)         返回类型若是基本类型,则必须保持一样,否则会报错;返回类型若是类对象,则可以允许返回值之间有继承关系(直接/间接继承都可以)即可(菱形继承除外)

c++虚函数&重写的更多相关文章

  1. c++虚函数重写的权限问题

    cbase.h: #ifndef CBASE_H #define CBASE_H #include<iostream> using std::cout; using std::endl; ...

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

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

  3. 你好,C++(37)上车的人请买票!6.3.3 用虚函数实现多态

    6.3.3  用虚函数实现多态 在理解了面向对象的继承机制之后,我们知道了在大多数情况下派生类是基类的“一种”,就像“学生”是“人”类中的一种一样.既然“学生”是“人”的一种,那么在使用“人”这个概念 ...

  4. C++基础 (7) 第七天 多态的原理 纯虚函数和抽象类 依赖倒置原则

    1 昨日回顾 2 多态的原理 1 要有继承 2 要有子类重写父类的虚函数 3 父类指针(或者引用)指向子类对象 (动态联编 虚函数表 3 证明vptr指针的存在 4 vptr指针在构造父类的时候是分步 ...

  5. 虚函数重载(overwrite) 继承覆盖问题

    引言 类接口需要添加默认参数,以适应不同情况调用, 但是clang-tidy 不允许在接口上设置默认参数,ps: 可能担心继承类里接口重新设置新默认参数而导致误用的情况 #include <st ...

  6. c++中的函数重载、函数重写、函数重定义

    目录 一.函数重载 二.函数重写 三.函数重定义 为了更加深刻的理解 函数重载.重写.重定义,我们可以带着如下这两个问题去思考: 1.子类中是否可以定义父类中的同名成员?为什么? 可以,因为子类与父类 ...

  7. cc32a_demo-32dk2j_cpp_纯虚函数与抽象类-txwtech

    //32dk2j_cpp_纯虚函数与抽象类cc32a_demo-txwtech//纯虚函数是用来继承用的//纯虚函数//抽象类-抽象数据类型//*任何包含一个或者多个纯虚函数的类都是抽象类//*不要/ ...

  8. 【转载】 C++多继承中重写不同基类中相同原型的虚函数

    本篇随笔为转载,原文地址:C++多继承中重写不同基类中相同原型的虚函数. 在C++多继承体系当中,在派生类中可以重写不同基类中的虚函数.下面就是一个例子: class CBaseA { public: ...

  9. c# 基础(重写与覆盖:接口与抽象,虚函数与抽象函数)

    总结 1:不管是重写还是覆盖都不会影响父类自身的功能(废话,肯定的嘛,除非代码被改). 2:当用子类创建父类的时候,如 C1 c3 = new C2(),重写会改变父类的功能,即调用子类的功能:而覆盖 ...

随机推荐

  1. 团队作业7——第二次项目冲刺(Beta版本12.09——12.10)

    1.当天站立式会议照片 本次会议在5号公寓3楼召开,本次会议内容:①:熟悉每个人想做的模块.②:根据项目要求还没做的完成. 2.每个人的工作 经过会议讨论后确定了每个人的分工 组员 任务 陈福鹏 倒计 ...

  2. PAT 甲级 1141 PAT Ranking of Institutions

    https://pintia.cn/problem-sets/994805342720868352/problems/994805344222429184 After each PAT, the PA ...

  3. sqlsever实现更改字段名

    新建表:create table [表名]([自动编号字段] int IDENTITY (1,1) PRIMARY KEY ,[字段1] nVarChar(50) default '默认值' null ...

  4. Js apply方法详解,及其apply()方法的妙用

    Js apply方法详解 我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这 ...

  5. mysql my.cnf 或my.ini配置文件参数解释(转):

    #*** client options 相关选项 ***# #以下选项会被MySQL客户端应用读取.注意只有MySQL附带的客户端应用程序保证可以读取这段内容.如果你想你自己的MySQL应用程序获取这 ...

  6. Linux_Nginx 安装

    官网:http://nginx.org/ 1.下载http://nginx.org/download/nginx-1.14.0.tar.gz 2.查看详情 [zwesy@localhost ~]$ l ...

  7. 联想本win10 virtualbox 安装centos

    (1)必须开发操作系统虚拟化功能,参考该百度经验 https://jingyan.baidu.com/article/8275fc864d423e46a03cf638.html (2)调整虚拟机硬盘和 ...

  8. windows 下查看进程开始运行的时间

    1. 打开运行 输入 msinfo32 然后在软件环境- 正在运行任务- 就能够看到运行开始的时间了.

  9. SQL有三个类型的索引,唯一索引 不能有重复,但聚集索引,非聚集索引可以有重复

    重要: (1) SQL如果创建时候,不指定类型那么默认是非聚集索引 (2) 聚集索引和非聚集索引都可以有重复记录,唯一索引不能有重复记录. (3) 主键 默认是加了唯一约束的聚集索引,但是也可以在主键 ...

  10. 对比数据库字段不同的sql (mysql版)

    -- 使用test库 `test_project_management` `oel_project_management` USE test; -- 旧表 DROP TABLE old_column_ ...