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. 机器学习基石 5 Training versus Testing

    机器学习基石 5 Training versus Testing Recap and Preview 回顾一下机器学习的流程图: 机器学习可以理解为寻找到 \(g\),使得 \(g \approx f ...

  2. 浅谈EL

    一.了解EL 1.EL是从 JavaScript 脚本语言得到启发的一种表达式语言,它借鉴了 JavaScript 多类型转换无关性的特点.在使用 EL 从 scope 中得到参数时可以自动转换类型, ...

  3. Sql Server优化---统计信息维护策略

    本位出处:http://www.cnblogs.com/wy123/p/5748933.html 首先解释一个概念,统计信息是什么: 简单说就是对某些字段数据分布的一种描述,让SQL Server大概 ...

  4. idea调试SpringMvc, 出现:”通配符的匹配很全面, 但无法找到元素 'mvc:annotation-driven' 的声明“错误的解决方法

    调试json格式输出,出现以下错误: HTTP Status 500 - Servlet.init() for servlet HelloDispatcher threw exception   ty ...

  5. 简单的add函数的N种写法

    最近在学习es6,看到for-of这里,就想自己写着练习一下,于是就准备写一个小函数add来求和.函数很简单,如add(1,2,3)这样.于是我开始着手 一开始我是这么写的 function add( ...

  6. 【iOS】7.4 定位服务->2.1.3.2 定位 - 官方框架CoreLocation 功能2:地理编码和反地理编码

    本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...

  7. ICC_lab总结——ICC_lab2:设计规划

    PS:字丑,禁止转载!!! 首先先写出大概的流程,然后是一些教材的理论知识总结,最后是进行lab2的一些流程概述. 教材的理论知识总结主要是:数字集成电路物理设计学习总结--布图规划和布局 --> ...

  8. SLF4J 的几种实际应用模式--之三:JCL-Over-SLF4J+SLF4J

    我们前面已经讲过了 SLF4J 的两种用法:SLF4J+Log4J  和 SLF4J+Logback,那是在比较理想的情况下,所用组件只使用了 SLF4J 这一种统一日志框架的时候.可是 JCL 一直 ...

  9. quartz笔记

    首先网络上的很多教程经常有错(信息过载了),其主要原因是版本发生了变化,例如quartz1和2之间还是有不少差别的,导致查找资料的人浪费了不少时间.所以无论教程如何写,都建议读者首先学习官网的教程,如 ...

  10. css gray,grayscale,css变灰兼容大部分浏览器

    css gray,grayscale,css变灰兼容大部分浏览器 html { filter: url("data:image/svg+xml;utf8,<svg xmlns=\'ht ...