#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虚函数的更多相关文章

  1. 【2016-10-13】【坚持学习】【Day4】【virtual 虚函数】

    定义一个基类,有一个虚函数 定义三个子类,分别继承,重写,New,这个虚函数   abstract class Test { public virtual void Prinf() { Console ...

  2. C++\virtual 虚函数、纯虚函数

    前提摘要: 虚函数联系到多态,多态联系到继承.所以本文中都是在继承层次上做文章.没了继承,什么都没得谈. 虚函数定义: 指向基类的指针或引用在操作它的多态类(子类/派生类)对象时,会根据不同的类对象, ...

  3. 23.C++- 继承的多种方式、显示调用父类构造函数、父子之间的同名函数、virtual虚函数

     上章链接: 22.C++- 继承与组合,protected访问级别 继承方式 继承方式位于定义子类的”:”后面,比如: class Line : public Object //继承方式是publi ...

  4. C#语法-虚方法详解 Virtual 虚函数

    虚方法 / Virtual 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享. ...

  5. c++中virtual 虚函数

    转载: https://www.cnblogs.com/weiyouqing/p/7544988.html 在面向对象的C++语言中,虚函数(virtual function)是一个非常重要的概念. ...

  6. 104.virtual虚函数多态与异构数据结构

    #include "mainwindow.h" #include <QApplication> #include <list> #include <Q ...

  7. C++之虚函数和多态

    干货较多-需要自己深思理解: C++支持两种多态性: 1.编译时多态性(静态绑定-早绑定) 在程序编译阶段即可以确定下来的多态性 通过使用 重载机制(重载函数)实现 (模板)http://blog.c ...

  8. TControl的显示函数(5个非虚函数,4个虚函数)和三个例子的执行过程(包括SetParent的例子)

    // 9个显示函数 procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); virtual; // 虚函数,important 根据父控 ...

  9. c++ 深入理解虚函数

    为什么使用虚函数?什么是虚函数?虚函数是为了解决什么问题? 面向对象的三大特征: 封装 多态 继承 普通虚函数 虚析构函数 纯虚函数 抽象类 接口类 隐藏 vs 覆盖 隐藏与覆盖之间的关系 早绑定和晚 ...

随机推荐

  1. jquery 进阶

    1.0 jquery的ajax同步和异步区别 2.0 cdnjquery加载失败加载本地 <script type="text/javascript" src="/ ...

  2. 一道java算法题分析

    最近在面试中遇到这样的一道算法题:       求100!的结果的各位数之和为多少?       如:5!=5*4*3*2*1=120,那么他们的和为1+2+0=3这道题不算难,不过倒是注意的细节也有 ...

  3. 求SQL语句递归的算法

    表结构是这样的 部门    上级部门    A           BB           CC           DA           AB           BC           C ...

  4. EF更新,数据库值变化,前台页面并不变化,刷新也不变化,重新运行程序则变化----开发中遇到的问题(已解决)

    首先说一下我遇到这个情况的代码情景,首先上错误代码 UserInfo userInfo = Session["UserInfo"] as UserInfo; ); 这段代码所呈现的 ...

  5. c#中高效的excel导入sqlserver的方法

    将oledb读取的excel数据快速插入的sqlserver中,很多人通过循环来拼接sql,这样做不但容易出错而且效率低下,最好的办法是使用bcp,也就是System.Data.SqlClient.S ...

  6. 介绍开源的.net通信框架NetworkComms框架 源码分析(十八 ) ConnectionListenerBase

    原文网址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 语言编写的TCP/UDP通信框架  作者是英国人  以前是收费的 目前作者已经开源  许可是 ...

  7. DataTable 除去列中重复值

    DataTable dtPCI = dtblSourceData.DefaultView.ToTable(true, new string[] { "Server Cell PCI" ...

  8. 【Java每日一题】20161130

    20161129问题解析请点击今日问题下方的"[Java每日一题]20161130"查看 package Nov2016; public class Ques1130 { publ ...

  9. css用背景图来替换文字来达到隐藏文字的目的

    根据html代码的不同来分成两大类方法,如下 html代码: <h1 class="replace-indent">hello see</h1> 第一种方法 ...

  10. 分享50款 Android 移动应用程序图标【上篇】

    在这个移动程序流行的时代,持续增长的应用程序经济充满了商业机遇.任何对应用程序设计感兴趣的人,将会喜欢上这里的50个独特的 Android 应用程序图标.这些例子中的图标能够让应用程序的设计更具吸引力 ...