1.虚函数

        virtual用来修饰父类函数中的普通函数,子类可以通过重写(与父类中的普通函数同名同参数)来覆盖父类中的函数的输出结果,即程序在运行时调用的是子类中的函数而不是父类。注意:在调用函数时(Barking()),我们用的父类的指针或引用指向子类对象。最终输出的结果是:

#include <iostream>
#include <string>using namespace std;
class Animals
{
public:virtual void Bark(){cout << "动物叫声" << endl;}
};
class Cat :public Animals
{
public:virtual void Bark(){cout << "喵喵喵" << endl;}
};
void Barking(Animals& animals)
{animals.Bark();
}
void text()
{Cat cat;Barking(cat);
}int main()
{text();
}

2.纯虚函数

        在解释纯虚函数之前,需要先明白一个问题,我们为什么要定义父类指针去指向子类对象,而不是直接用子类指针指向子类对象,下面这篇博客很好的解释了这个问题。父类引用指向子类对象_gideal_wang的博客-CSDN博客父类引用指向子类对象指的是:例如父类Animal,子类Cat,Dog。其中Animal可以是类也可以是接口,Cat和Dog是继承或实现Animal的子类。Animal animal = new Cat();即声明的是父类,实际指向的是子类的一个对象。 那这么使用的优点是什么,为什么要这么用?可以用这几个关键词来概括:多态、动态链接,向上转型也有人说这是面向接口编程,可以降低https://blog.csdn.net/gideal_wang/article/details/4913965?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166692105116782427487200%2522%252C%2522scm%2522%253A%252220140713.130212432.pc%255Fall.%2522%257D&request_id=166692105116782427487200&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~pc_ctr_v1-8-4913965-null-null.142%5Ev62%5Eopensearch_v2,201%5Ev3%5Eadd_ask,213%5Ev1%5Econtrol&utm_term=%E7%88%B6%E7%B1%BB%E6%8C%87%E9%92%88%E6%8C%87%E5%90%91%E5%AD%90%E7%B1%BB%E5%AF%B9%E8%B1%A1&spm=1018.2226.3001.4187        虚函数的输出结果可知,若所有子类中均重写了父类的一个虚函数,那么程序将不会调用父函数中的虚函数,这时,我们可以将这个父类中的虚函数定义成一个纯虚函数。

        纯虚函数的定义方式:virtual  返回值类型  函数名(参数列表)  =  0;

        值得注意的是,当类中出现了纯虚函数,那么该类不能实例化对象;子类继承了父类中的纯虚函数而不是重写父类中的纯虚函数时,子类也不能实例化对象。

#include <iostream>
#include <string>using namespace std;
class Animals
{
public:virtual void Bark() = 0;
};
class Cat :public Animals
{
public:virtual void Bark(){cout << "喵喵喵" << endl;}
};
void Barking(Animals& animals)
{animals.Bark();
}
void text()
{Cat cat;Barking(cat);
}int main()
{text();
}

3.虚析构函数

        若不使用virtual修饰父类的析构函数,又使用了父类指针去指向子类对象,我们在最后delete实例化的对象(cat)的时候,系统不会调用Cat类的析构函数。运行结果:

#include <iostream>
#include <string>using namespace std;
class Animals
{
public:virtual void Bark() = 0;Animals() {cout << "Animals的构造" << endl;}~Animals(){cout << "Animals的析构" << endl;}
};
class Cat :public Animals
{
public:Cat(){cout << "Cat的构造" << endl;}virtual void Bark(){cout <<  "喵喵喵" << endl;}~Cat(){cout << "Cat的析构" << endl;}
};void text()
{Animals* cat = new Cat;cat->Bark();delete cat;}int main()
{text();
}

        若在使用Cat类的构造函数中new一个类(也就是自己申请一块地址,该参数存放在堆区,需要手动delete),而父类又不能调用子类的析构函数,这时我们需要用到virtual关键字去修饰父类的析构函数,从而达到手动释放堆区参数的目的。最终结果:

#include <iostream>
#include <string>using namespace std;
class Animals
{
public:virtual void Bark() = 0;Animals() {cout << "Animals的构造" << endl;}virtual ~Animals(){cout << "Animals的析构" << endl;}
};
class Cat :public Animals
{
public:string* m_Name;Cat(string name){m_Name = new string(name);cout << "Cat的构造" << endl;}virtual void Bark(){cout << *m_Name << "喵喵喵" << endl;}~Cat(){if (m_Name != NULL){delete m_Name; //delete一个指针后,编译器只是释放了指针中存放的地址中的内存空间,//但p中存放的地址还是原来的地址,//这时成为一个野指针,为了杜绝这种情况的发生,我们需要置NULLm_Name = NULL;}cout << "Cat的析构" << endl;}
};void text()
{Animals* cat = new Cat("Tom");cat->Bark();delete cat;
}int main()
{text();
}

        题外:为什么需要new一个类,而不是直接用最基础的参数定义方式,就是int number这种自动变量。其中一个原因是自动变量在离开作用域后回自动释放。

3.纯虚析构函数

        感觉没屁用。。。

C++的动态多态,Virtual关键字的作用相关推荐

  1. C++之静态联编与动态联编及virtual关键字的作用

    定义 将一个调用函数连接上正确的被调用函数,这个过程就叫做函数的联编,简称联编.在C++中,一共有两种联编的方式: 静态联编 #define:静态联编是指联编工作出现 在编译连接阶段. 特点:① 静态 ...

  2. 【学习笔记】C++ 中的 virtual 关键字与虚函数

    目录 先决条件 前言 演示示例 virtual 关键字的作用 虚函数的规则 参考与拓展 深入拓展 先决条件 了解 C++ 中的多态这个概念. 前言 virtual 关键字是面对对象中,用于修饰类中的成 ...

  3. EF实体类种的Virtual关键字作用

    在使用EF中我们会使用导航属性,其中会加上Virtual关键字,这个有什么作用呢.加了此关键字就可以使用lazyload懒加载,不加此特性的话是加载不出此导航属性的内容的. 例子,有两个实体sys_u ...

  4. 新手福利——理解java多态的概念和作用

    多态是面向对象的重要特性,简单点说:"一个接口,多种实现",就是同一种事物表现出的多种形态. 编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物 ...

  5. 【C++】动态多态与虚函数

    文章目录 一.动态多态概念 二.虚函数 2.1 虚函数的概念 2.2 虚函数的特点 三.动态多态实现的背后编译器帮我做了什么? 四.虚析构 4.1 解决多态中资源释放的问题 4.2 解决多重继承中的资 ...

  6. C++多态,虚函数作用及底层实现原理

    简述C++虚函数作用及底层实现原理 1.foreword C++是面向对象程序设计,其包括3项特点: (1)数据抽象:接口和实现分离 (2)继承:父类和子类 (3)多态:动态绑定 本文讨论多态. 当父 ...

  7. 【C++ 语言】面向对象 ( 继承 | 重写 | 子类调用父类方法 | 静态多态 | 动态多态 | 虚函数 | 纯虚函数 )

    文章目录 类的继承 方法的重写 子类中调用父类方法 多态 虚函数 虚函数示例 纯虚函数 相关代码 类的继承 1. 继承表示 : C++ 中继承可以使用 ":" 符号 , 格式为 & ...

  8. virtual析构函数的作用?

    *************************************************** 更多精彩,欢迎进入:http://shop115376623.taobao.com ****** ...

  9. virtual析构函数(作用)

    virtual析构函数的作用? . 大家知道,析构函数是为了在对象不被使用之后释放它的资源,虚函数是为了实现多态.那么把析构函数声明为vitual有什么作用呢?请看下面的代码: 1 #include ...

最新文章

  1. web自动化测试—selenium游览器下拉框操作
  2. Visual Studio中使用Git Flow
  3. 线性调频信号(LFM)的形式及幅度谱、相位谱特性
  4. iOS: 彻底理解position与anchorPoint
  5. android 底部选项,Android:底部的选项卡
  6. python深度学习机器学习必备的学习网站集合!
  7. cocos2d-x初步
  8. 根据数据库中提供的坐标(经纬度) 在前端地图上标示坐标点、并显示
  9. 裸机服务器装系统步骤,组装裸机如何装系统?
  10. 新手小白安装linux系统
  11. android涟漪动画,如何添加涟漪效果并在android中的按钮上有自定义背景?
  12. 蓝桥杯真题:三羊献瑞
  13. 经纬度坐标点和距离之间的转换
  14. 2018-10-29 直播课笔记
  15. 哨兵2号(Sentinel2)卫星数据处理
  16. dos2unix和unix2dos
  17. 华为交换机——批量将端口加入VLAN
  18. xcode 下载中断问题
  19. AI与大数据结合,有效提高预测,构建更好的内容营销
  20. Refind安装……

热门文章

  1. 【2020百度发帖教学】百度贴吧怎么发帖顶帖?发广告图不删?还能带联系方式推广?
  2. Hibernate 之主键生成策略
  3. 首次报考一级消防工程师证好考吗? 有什么技巧吗?
  4. 三大措施助力连接提速 网易云信打造智慧IM云架构
  5. H5和PC端开发差异对比
  6. 怎样从PHP文件中提取特征码,关于判断文件唯一性,怎么提取特征码
  7. 最简单的ssm框架整合搭建
  8. tair mysql_MySQL数据库异构数据同步–后端以tair为例
  9. android分组流式布局,Android 流式布局实现
  10. PHP接入腾讯云行驶证识别(新旧版本,不使用SDK及DEMO)