C++中有无数的坑,但毕竟……

今天就踩到了,也算是基本问题了,记录一下,顺便以后可以考考自己。你也可以猜猜答案,大牛绕行。

0x1 先看这个:

 #include <stdio.h>
#include <stdlib.h> class App
{
public:
~App()
{
printf("\n~App\n");
}
void output()
{
printf("A");
}
}; class Bpp : public App
{
public:
~Bpp()
{
printf("\n~Bpp\n");
}
void output()
{
printf("B");
}
}; int main(char args[])
{
Bpp* b = new Bpp();
delete b; system("pause");
return ;
}

结果:

~Bpp

~App
请按任意键继续. . .

0x02 : 再来 ,改了第32行

 #include <stdio.h>
#include <stdlib.h> class App
{
public:
~App()
{
printf("\n~App\n");
}
void output()
{
printf("A");
}
}; class Bpp : public App
{
public:
~Bpp()
{
printf("\n~Bpp\n");
}
void output()
{
printf("B");
}
}; int main(char args[])
{
App* b = new Bpp();
delete b; system("pause");
return ;
}

结果:

~App
请按任意键继续. . .

0x03 下一个 改动 7 line

 #include <stdio.h>
#include <stdlib.h> class App
{
public:
virtual ~App()
{
printf("\n~App\n");
}
void output()
{
printf("A");
}
}; class Bpp : public App
{
public:
~Bpp()
{
printf("\n~Bpp\n");
}
void output()
{
printf("B");
}
}; int main(char args[])
{
App* b = new Bpp();
delete b; system("pause");
return ;
}

结果:

~Bpp

~App
请按任意键继续. . .

0x04 next 改动 line 20

 #include <stdio.h>
#include <stdlib.h> class App
{
public:
virtual ~App()
{
printf("\n~App\n");
}
void output()
{
printf("A");
}
}; class Bpp : public App
{
public:
virtual ~Bpp()
{
printf("\n~Bpp\n");
}
void output()
{
printf("B");
}
}; int main(char args[])
{
App* b = new Bpp();
delete b; system("pause");
return ;
}

结果和 0x03一样:

~Bpp

~App
请按任意键继续. . .

0x05 接着 再在第7 行中 去掉 virtual

 #include <stdio.h>
#include <stdlib.h> class App
{
public:
~App()
{
printf("\n~App\n");
}
void output()
{
printf("A");
}
}; class Bpp : public App
{
public:
virtual ~Bpp()
{
printf("\n~Bpp\n");
}
void output()
{
printf("B");
}
}; int main(char args[])
{
App* b = new Bpp();
delete b; system("pause");
return ;
}

结果:

在33行,程序报错,崩溃。

0x6 改动 32行:

 #include <stdio.h>
#include <stdlib.h> class App
{
public:
~App()
{
printf("\n~App\n");
}
void output()
{
printf("A");
}
}; class Bpp : public App
{
public:
virtual ~Bpp()
{
printf("\n~Bpp\n");
}
void output()
{
printf("B");
}
}; int main(char args[])
{
void* b = new Bpp();
delete b; system("pause");
return ;
}

结果:执行成功。

请按任意键继续. . .

0x07 把所有 virtual 去掉

#include <stdio.h>
#include <stdlib.h> class App
{
public:
~App()
{
printf("\n~App\n");
}
void output()
{
printf("A");
}
}; class Bpp : public App
{
public:
~Bpp()
{
printf("\n~Bpp\n");
}
void output()
{
printf("B");
}
}; int main(char args[])
{
void* b = new Bpp();
delete b; system("pause");
return ;
}

结果:

请按任意键继续. . .

0x08 加上所有 virtual :

 #include <stdio.h>
#include <stdlib.h> class App
{
public:
virtual ~App()
{
printf("\n~App\n");
}
void output()
{
printf("A");
}
}; class Bpp : public App
{
public:
virtual ~Bpp()
{
printf("\n~Bpp\n");
}
void output()
{
printf("B");
}
}; int main(char args[])
{
void* b = new Bpp();
delete b; system("pause");
return ;
}

结果:

请按任意键继续. . .

0x09 最后:

 #include <stdio.h>
#include <stdlib.h> class App
{
public:
~App()
{
printf("\n~App\n");
}
void output()
{
printf("A");
}
}; class Bpp : public App
{
public:
virtual ~Bpp()
{
printf("\n~Bpp\n");
}
void output()
{
printf("B");
}
}; int main(char args[])
{
Bpp* b = new Bpp();
delete b; system("pause");
return ;
}

结果,可以猜猜:

 ~Bpp

 ~App
请按任意键继续. . .

最后的答案

结语:

1. 通常应该给基类提供一个虚析构函数,即使它不需要析构函数 —— 《C++ Primer Plus (第6版)中文版》, 505页

2. 如果一个类带有任何 virtual 函数,这个类就应该拥有 virtual 析构函数 —— 《Effective C++ 中文版,第三版》,条款07:为多态基类声明 virtual 析构函数,44页

3. 如果一个类被当作基类(也就是说这个类需要被其他类继承),那这个类的析构函数就要加上 virual 关键字!

【日常】C++ 的那些“坑” —— delete 与 析构函数 与 virtual 的 9 个小例子的更多相关文章

  1. new、delete、析构函数、自动类型转换

    new 分配内存,返回指针 new 类型名T (初值列表) 功能:申请用于存放T类型对象的内存空间,并依初值列表赋以初值 结果值: 成功->T类型的指针,指向新分配的内存 失败->0(NU ...

  2. delete和析构函数

    new一个类的时候,调用这个类的构造函数,然后在这个类的生命周期内可能会动态生成很多指向堆上的内存,所以应该在析构函数里回收这些内存: 当delete这个类的时候,会首先调用这个类的析构函数,即回收生 ...

  3. JavaScript日常会跳的坑系列(二)

    1.Number()将部分非数字类型转换为0 强制转换为数值类型函数: parseFloat.parseInt 优点:对非数值类型统一返回NaN 缺点:会将一部分符合数值类型的字符串也识别为数值 pa ...

  4. C++类继承--基类析构函数加上Virtual

    下面的内容要说明两个问题:1. 基类的析构函数为什么要加上Virtual--防止内存泄露 1. 基类虚构函数无virtual,派生类无法析构,会导致内存泄露 #include <stdio.h& ...

  5. C++类中使用new及delete小例子

    //默认复制构造函数的不足//尽管有默认的复制构造函数来解决一般对象与对象之间的初始化问题, 但是在有些情况下我们必须手动显式的去定义复制构造函数, 例如: #include <iostream ...

  6. activiti 用户手册中 10分钟 小例子 简单代码搭建 及 其中的 各种坑

    看mossle的 5.16 用户手册中的  快速起步:10分钟教程 想自己跑一下,虽然官方文档已经写的非常详细了,但是实际操作中还是遇到各种坑,这里记录下来. 首先官网下载最新的 5版本 full G ...

  7. C++类中使用new及delete小例子(续)

    在该示例中我们显式定义了复制构造函数来代替默认复制构造函数, 在该复制构造函数的函数体内, 不是再直接将源对象所申请空间的地址赋值给被初始化的对象, 而是自己独立申请一处内存后再将源对象的属性复制过来 ...

  8. C/C++ New与Delete (小例子)

    转自:http://blog.csdn.net/chenzujie/article/details/7011639   先来看两段小程序: 1). #include <iostream.h> ...

  9. Chrome 开发者工具中的命令菜单

    单 大家对命令菜单(Command Menu)应该都不陌生.目前主流的编辑器中都内置了对该功能的支持.在 Sublime Text 和 Visual Studio Code 中你都可以通过快捷键 Ct ...

随机推荐

  1. UIBeaierPath 与 CAShapeLayer

    CAShapeLayer是基于贝塞尔曲线而存在的, 如果没有贝塞尔曲线提供路径来画出图形, CAShapeLayer就没有存在的意义, CAShapeLayer可以使得不用在   drawRect:方 ...

  2. iOS开发之iOS程序的启动过程

    程序启动的完整过程: (1)main函数 (2)UIApplicationMain * 创建UIApplication对象 * 创建UIApplication的delegate对象 (3)delega ...

  3. 一步步教你使用rem适配不同屏幕的移动设备

    1.先说说几个前端常用的几个单位的概论: 1.px (pixel,像素):是一个虚拟长度单位,是计算机系统的数字化图像长度单位,如果px要换算成物理长度,需要指定精度DPI(Dots Per Inch ...

  4. sass ruby环境 安装配置,使用sublime text3 中sass

    首先,你想要使用sass的话,就必须依赖于ruby环境.所以,你要下一个ruby.具体的链接应该是(http://rubyinstaller.org/downloads).下载相应的版本.- 下载好之 ...

  5. javaWEB与Session

    HttpSession(*****)1. HttpSession概述  * HttpSession是由JavaWeb提供的,用来会话跟踪的类.session是服务器端对象,保存在服务器端!!!  * ...

  6. SQL Server 获取本周,本月,本年等时间内记录

    datediff(week,zy_time,getdate())=0 //查询本周 datediff(month,zy_time,getdate())=0 //查询本月 本季:select * fro ...

  7. Windows运行命令大全

    inetmgr   启动IIS控制台winver 检查Windows版本 wmimgmt.msc 打开Windows管理体系结构(wmi) wupdmgr Windows更新程序 wscript Wi ...

  8. Windows 10 系统Microsoft Edge的使用手册

    Windows 10 默认浏览器(Edge)使用手册 体验网络有了一种新的方法.只有在 Windows 10 上才能找到它. 下面详细介绍一下Edge浏览器的使用规范: 一.打开Windows10系统 ...

  9. JPlayer Jquery video视频插件

    近日一直在搜关于视频的jquery插件,要求功能全,跨平台,百思不得其解,偶尔找到一个插件JPlayer,国产的,很全.为什么选择JPlayer 简单:几分钟就可以上手编码.部署 可定制:可以方便地用 ...

  10. JavaWeb之cookie

    什么叫做会话 ? 用户从打开一个浏览器开始,浏览器网站,到关闭浏览器的整个过程叫做一次会话! 每个用户与服务器进行交互的过程中,各自会有一些数据,程序要想办法保存每个用户的数据. 例如:用户点击超链接 ...