C++的动态多态,Virtual关键字的作用
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关键字的作用相关推荐
- C++之静态联编与动态联编及virtual关键字的作用
定义 将一个调用函数连接上正确的被调用函数,这个过程就叫做函数的联编,简称联编.在C++中,一共有两种联编的方式: 静态联编 #define:静态联编是指联编工作出现 在编译连接阶段. 特点:① 静态 ...
- 【学习笔记】C++ 中的 virtual 关键字与虚函数
目录 先决条件 前言 演示示例 virtual 关键字的作用 虚函数的规则 参考与拓展 深入拓展 先决条件 了解 C++ 中的多态这个概念. 前言 virtual 关键字是面对对象中,用于修饰类中的成 ...
- EF实体类种的Virtual关键字作用
在使用EF中我们会使用导航属性,其中会加上Virtual关键字,这个有什么作用呢.加了此关键字就可以使用lazyload懒加载,不加此特性的话是加载不出此导航属性的内容的. 例子,有两个实体sys_u ...
- 新手福利——理解java多态的概念和作用
多态是面向对象的重要特性,简单点说:"一个接口,多种实现",就是同一种事物表现出的多种形态. 编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物 ...
- 【C++】动态多态与虚函数
文章目录 一.动态多态概念 二.虚函数 2.1 虚函数的概念 2.2 虚函数的特点 三.动态多态实现的背后编译器帮我做了什么? 四.虚析构 4.1 解决多态中资源释放的问题 4.2 解决多重继承中的资 ...
- C++多态,虚函数作用及底层实现原理
简述C++虚函数作用及底层实现原理 1.foreword C++是面向对象程序设计,其包括3项特点: (1)数据抽象:接口和实现分离 (2)继承:父类和子类 (3)多态:动态绑定 本文讨论多态. 当父 ...
- 【C++ 语言】面向对象 ( 继承 | 重写 | 子类调用父类方法 | 静态多态 | 动态多态 | 虚函数 | 纯虚函数 )
文章目录 类的继承 方法的重写 子类中调用父类方法 多态 虚函数 虚函数示例 纯虚函数 相关代码 类的继承 1. 继承表示 : C++ 中继承可以使用 ":" 符号 , 格式为 & ...
- virtual析构函数的作用?
*************************************************** 更多精彩,欢迎进入:http://shop115376623.taobao.com ****** ...
- virtual析构函数(作用)
virtual析构函数的作用? . 大家知道,析构函数是为了在对象不被使用之后释放它的资源,虚函数是为了实现多态.那么把析构函数声明为vitual有什么作用呢?请看下面的代码: 1 #include ...
最新文章
- web自动化测试—selenium游览器下拉框操作
- Visual Studio中使用Git Flow
- 线性调频信号(LFM)的形式及幅度谱、相位谱特性
- iOS: 彻底理解position与anchorPoint
- android 底部选项,Android:底部的选项卡
- python深度学习机器学习必备的学习网站集合!
- cocos2d-x初步
- 根据数据库中提供的坐标(经纬度) 在前端地图上标示坐标点、并显示
- 裸机服务器装系统步骤,组装裸机如何装系统?
- 新手小白安装linux系统
- android涟漪动画,如何添加涟漪效果并在android中的按钮上有自定义背景?
- 蓝桥杯真题:三羊献瑞
- 经纬度坐标点和距离之间的转换
- 2018-10-29 直播课笔记
- 哨兵2号(Sentinel2)卫星数据处理
- dos2unix和unix2dos
- 华为交换机——批量将端口加入VLAN
- xcode 下载中断问题
- AI与大数据结合,有效提高预测,构建更好的内容营销
- Refind安装……
热门文章
- 【2020百度发帖教学】百度贴吧怎么发帖顶帖?发广告图不删?还能带联系方式推广?
- Hibernate 之主键生成策略
- 首次报考一级消防工程师证好考吗? 有什么技巧吗?
- 三大措施助力连接提速 网易云信打造智慧IM云架构
- H5和PC端开发差异对比
- 怎样从PHP文件中提取特征码,关于判断文件唯一性,怎么提取特征码
- 最简单的ssm框架整合搭建
- tair mysql_MySQL数据库异构数据同步–后端以tair为例
- android分组流式布局,Android 流式布局实现
- PHP接入腾讯云行驶证识别(新旧版本,不使用SDK及DEMO)