C++ virtual虚函数
#include<iostream>
using namespace std;
class Base{
public:
void m()
{
cout << "it's Base's m() " << endl;
}
virtual void f()
{
cout << "it's Base's f()" << endl;
}
};
class Sub: public Base
{
void m()
{
cout << "it's Sub's m()" << endl;
}
void f()
{
cout << "it's Sub's f()" << endl;
}
};
void main()
{
Base* base = new Sub;
base->f();
base->m();
}
上述是以Base为基类,并且Sub派生了Base,同时复写了两个函数f(),m()
当在主函数main里用Base类型的指针指向Sub类型对象,此时利用Base指针调用f()和m(),那么这个时候问题就来了。
在默认情况下Base类的指针会调用当前类型的方法,也就是Base::f(),Base::m(),那么应该输出的都是Base方法中的语句
然而结果输出的是
为什么会产生这种原因呢?
因为父类的f()是虚函数,那么当基类指针调用它的派生类对象时,会默认调用多态性对象的相应方法,于是就解释了为什么Base* base->f()调用了派生类Sub的f()的方法,
由此我们可以知道虚函数Virtual主要是为了解决多态性问题,因为一个基类方法定义后,它的派生类对象会针对此方法进行不同的覆盖实现,即多态性,若你此时利用基类的指针来指向基类的多态性子类,那么就需要利用virtual修饰基类方法,从而可以来调用你所需要的派生类的方法而避免了调用基类的此方法。
Virtual是C++ OO机制中很重要的一个关键字。在类Base中加了Virtual关键字的函数就是虚拟函数(例如函数print),于是在Base的派生类Derived中就可以通过重写虚拟函数来实现对基类虚拟函数的覆盖。当基类Base的指针point指向派生类Derived的对象时,对point的print函数的调用实际上是调用了Derived的print函数而不是Base的print函数。这是面向对象中的多态性的体现。
还有虚函数析构函数,应用在这样一个问题:在基类为抽象类,并且基类指针指向派生类,想要删除这个基类指针指向的内存时
先看第一种情况
de<iostream>
using namespace std;
class Base{
public:
Base()
{
}
~Base()
{
cout << "Base has deleted" << endl;
}
};
class Sub: public Base
{
public:
Sub()
{
}
~Sub()
{
cout << "Sub has delete" << endl;
}
};
void main()
{
Base* base = new Sub;
delete base;
base = NULL;
}
看运行结果

此时是用基类Base指针去操作继承类Sub,在delete Base*指针后,我们可以从结果得到只调用了基类的析构函数,但是派生类的析构函数并没有调用,这相当于内存只是删除了一一半,还有一半内存为删除,导致了内存泄漏,此时则需要用到虚析构函数,来达到调用派生类的析构函数来删除内存空间的目的,也就是下面这种情况:
#include<iostream>
using namespace std;
class Base{
public:
Base()
{
}
virtual ~Base()
{
cout << "Base has deleted" << endl;
}
};
class Sub: public Base
{
public:
Sub()
{
}
~Sub()
{
cout << "Sub has delete" << endl;
}
};
void main()
{
Base* base = new Sub;
delete base;
base = NULL;
}
运行结果如下图所示

此时我们可以看到在基类析构函数加了Virtual变成虚函数后,成功地调用了基类和派生类的析构函数,从而实现了基类指针指向内存的完全释放。
虚析构函数工作的方式是:最底层的派生类的析构函数最先被调用,然后各个基类的析构函数被调用。
但是有一点要注意,当某个类没有虚函数时,那么此类不会被当作基类,此时定义虚析构函数只会增加内存开销,因为需要开启一个虚函数列表来储存。
以上只是个人的小总结,若有错误,欢迎前来纠正!
C++ virtual虚函数的更多相关文章
- 【2016-10-13】【坚持学习】【Day4】【virtual 虚函数】
定义一个基类,有一个虚函数 定义三个子类,分别继承,重写,New,这个虚函数 abstract class Test { public virtual void Prinf() { Console ...
- C++\virtual 虚函数、纯虚函数
前提摘要: 虚函数联系到多态,多态联系到继承.所以本文中都是在继承层次上做文章.没了继承,什么都没得谈. 虚函数定义: 指向基类的指针或引用在操作它的多态类(子类/派生类)对象时,会根据不同的类对象, ...
- 23.C++- 继承的多种方式、显示调用父类构造函数、父子之间的同名函数、virtual虚函数
上章链接: 22.C++- 继承与组合,protected访问级别 继承方式 继承方式位于定义子类的”:”后面,比如: class Line : public Object //继承方式是publi ...
- C#语法-虚方法详解 Virtual 虚函数
虚方法 / Virtual 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享. ...
- c++中virtual 虚函数
转载: https://www.cnblogs.com/weiyouqing/p/7544988.html 在面向对象的C++语言中,虚函数(virtual function)是一个非常重要的概念. ...
- 104.virtual虚函数多态与异构数据结构
#include "mainwindow.h" #include <QApplication> #include <list> #include <Q ...
- C++之虚函数和多态
干货较多-需要自己深思理解: C++支持两种多态性: 1.编译时多态性(静态绑定-早绑定) 在程序编译阶段即可以确定下来的多态性 通过使用 重载机制(重载函数)实现 (模板)http://blog.c ...
- TControl的显示函数(5个非虚函数,4个虚函数)和三个例子的执行过程(包括SetParent的例子)
// 9个显示函数 procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); virtual; // 虚函数,important 根据父控 ...
- c++ 深入理解虚函数
为什么使用虚函数?什么是虚函数?虚函数是为了解决什么问题? 面向对象的三大特征: 封装 多态 继承 普通虚函数 虚析构函数 纯虚函数 抽象类 接口类 隐藏 vs 覆盖 隐藏与覆盖之间的关系 早绑定和晚 ...
随机推荐
- LINUX总结
LINUX总结 crazyacking 2016-02-26 主要对socket编程,多线程,定时器,条件变量总结 多线程篇 概念: 多线程就是允许一个进程内存存在多个控制权,实现多个线程并发执行. ...
- 功能更新到 Windows 10 企业版, 版本 1607
功能更新到 Windows 10 企业版, 版本 1607
- MySQL 函数大全
mysql函数大全 对于针对字符串位置的操作,第一个位置被标记为1. ASCII(str) 返回字符串str的最左面字符的ASCII代码值.如果str是空字符串,返回0.如果str是NULL,返回NU ...
- ASP.NET MVC初识
最近在博客园看到了很多关于MVC的示例,自己打算写下来记录一下,如果有写得不对的地方,望大侠指出! 开始搭建项目 1. 建立Web项目 文件—>新建项目—>选择ASP.NET MVC4 W ...
- LINQ的Except方法
在两个集合中,左边集合减去右边集合的元素: source code: List<int> a = new List<int>{ { }, { }, { } }; List< ...
- WinForm对话框
WinForm 对话框控件colorDialog - 颜色选择对话框 使用代码如下: private void 字体颜色ToolStripMenuItem_Click(object sender, E ...
- DSOFramerControl简单使用
以前大学做项目(Web的毕业论系统)就看见过在网页中嵌入Office的word,那时候用了哪个控件当时没记下来,我倒是忘了,最近发现在WinForm要嵌入Office的话,可以使用DSOFramerC ...
- Guava并发:ListenableFuture与RateLimiter示例
ListenableFuture顾名思义就是可以监听的Future,它是对java原生Future的扩展增强 RateLimiter类似于JDK的信号量Semphore,他用来限制对资源并发访问的线程 ...
- 最近Google经常打不开?
最近听好多同事讲google打不开,无法进行搜索,用了代理之后速度还是很慢,而百度搜索又不佳… 就在此分享一些google地址: 个人收藏夹的: 203.208.46.144(这段时间推荐使用这4个地 ...
- Struts2之Struts2-2.5.5 Interceptor
Struts2-2.5.5版本是目前为止最新的版本了,相对于之前的2.3版本以及再之前的版本而言,新版本改动了很多. 好了,废话不多说,GO CODE! 基本jar包: web.xml核心配置,这里要 ...