先看代码:

 #include<iostream>
using namespace std; class Parent {
public:
Parent() :a(), b(), c()
{ p = new char[];
//strcpy(p, "abc");
cout << "parent 无参构造。。。\n";
}
Parent(int test) :a(), b(), c()
{
p = new char[];
//strcpy(p, "abc");
cout << "parent 有参构造。。。\n";
}
~Parent()
{
delete[] p;
cout << "Parent 析构。。。\n";
}
int a;
int b;
int c;
char *p;
void p_print()
{
cout << "a b c is" << a << " " << b << " " << c << endl;
} };
class Child1 : public Parent
{
public:
Child1() :Parent(),a(), b(), c()
{
p = new char[];
// strcpy(p, "abc");
cout << "child1 构造\n";
}
~Child1()
{
delete[] p;
cout << "child1 析构,,,\n";
}
void c1_print()
{
cout << "a b c is" << a << " " << b << " " << c << endl;
} int a;
int b;
int c;
char *p;
};
class Child2 : public Child1
{
public:
Child2() :Child1(), b(), c()
{
p = new char[];
//strcpy(p, "abc");
cout << "child2 构造\n";
}
~Child2()
{
delete[] p;
cout << "child2 析构,,,\n";
}
void c2_print()
{
cout << "a b c is" << Parent::a << " " << b << " " << c << endl;
}
//int a;
int b;
int c;
char *p;
};
/*
class Child3 : public Child1, public Child2
{
public:
Child3() : Child1(), Child2(), b(20), c(30) { cout << "child 构造\n"; }
~Child3()
{
cout << "child 析构,,,\n";
}
void c3_print()
{
cout << "a b c is" << a << " " << b << " " << c << endl;
}
//int a;
int b;
int c;
};
*/
void play()
{
Child2* c2 = new Child2;
delete c2;
}
int main()
{
//Child2* c2 = new Child2;
play();
return ;
}

这样是没问题的(c++编译器会以构造相反的顺序执行析构函数),但是,在很多时候,我们不能在调用函数末尾就delete掉这个内存,还需要和后续交互。比如作为函数参数,为了实现多态,我们函数参数是父类的指针,所以更常见和一般的设计思维是更改paly和main函数如下:

 void play(Parent* p)
{
delete p;
}
int main()
{
Child2* c2 = new Child2;
play(c2);
return ;
}

运行结果显示内存泄漏了,只析构了父类;所以我们有那么一种需求,要想和多态的效果一样,传什么指针去,自动析构应该析构的东西,更改代码,实现虚析构函数。

只用更改基类的析构函数,加上virtual关键字:

     virtual ~Parent()
{
delete[] p;
cout << "Parent 析构。。。\n";
}

这样就没有内存泄漏了。

知识简要:

如果基类的析构函数不是虚函数,则delete一个指向派生类对象的基类指针将产生未定义的行为。之前我们介绍过一个准则,如果一个类需要析构函数,那么它同样需要拷贝和赋值操作。基类的析构函数并不遵循上述准则,它是一个重要的例外。

c++之——虚析构函数的更多相关文章

  1. c++虚析构函数

    虚析构函数的作用主要是当通过基类指针删除派生类对象时,调用派生类的析构函数(如果没有将不会调用派生类析构函数) #include <iostream> using namespace st ...

  2. EC笔记,第二部分:7.为多态基类声明虚析构函数

    7.为多态基类声明虚析构函数 1.为多态基类声明虚析构函数 code1: class A{ public: int* a; A():a(new int(5)) {} ~A(){ delete a; } ...

  3. C++浅析——继承类内存分布和虚析构函数

    继承类研究 1. Code 1.1 Cbase, CTEST为基类,CTest2为其继承类,并重新申明了基类中的同名变量 class CBase { public: int Data; CBase() ...

  4. 虚析构函数(√)、纯虚析构函数(√)、虚构造函数(X)

    from:http://blog.csdn.net/fisher_jiang/article/details/2477577 一. 虚析构函数 我们知道,为了能够正确的调用对象的析构函数,一般要求具有 ...

  5. C++学习24 虚析构函数

    在C++中,构造函数用于在创建对象时进行初始化工作,不能声明为虚函数.因为在执行构造函数前对象尚未创建完成,虚函数表尚不存在,也没有指向虚函数表的指针,所以此时无法查询虚函数表,也就不知道要调用哪一个 ...

  6. 从零开始学C++之虚函数与多态(一):虚函数表指针、虚析构函数、object slicing与虚函数

    一.多态 多态性是面向对象程序设计的重要特征之一. 多态性是指发出同样的消息被不同类型的对象接收时有可能导致完全不同的行为. 多态的实现: 函数重载 运算符重载 模板 虚函数 (1).静态绑定与动态绑 ...

  7. 从零开始学C++之虚函数与多态(二):纯虚函数、抽象类、虚析构函数

    一.纯虚函数 虚函数是实现多态性的前提 需要在基类中定义共同的接口 接口要定义为虚函数 如果基类的接口没办法实现怎么办? 如形状类Shape 解决方法 将这些接口定义为纯虚函数 在基类中不能给出有意义 ...

  8. C/C++中的虚析构函数和私有析构函数的使用

    代码: #include <iostream> using namespace std; class A{ public: A(){ cout<<"construct ...

  9. C++中基类的析构函数为什么要用virtual虚析构函数

    知识背景 要弄明白这个问题,首先要了解下C++中的动态绑定. 关于动态绑定的讲解,请参阅:  C++中的动态类型与动态绑定.虚函数.多态实现 正题 直接的讲,C++中基类采用virtual虚析构函数是 ...

  10. c++ 虚析构函数[避免内存泄漏]

    c++  虚析构函数: 虚析构函数(1)虚析构函数即:定义声明析构函数前加virtual 修饰, 如果将基类的析构函数声明为虚析构函数时,由该基类所派生的所有派生类的析构函数也都自动成为虚析构函数. ...

随机推荐

  1. 对threading模块源码文件的解读(不全)

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #对threading模块源码文件的解读(不全) import threading #类 #Thread() ...

  2. python第三方包的windows安装文件exe格式

    今天弄了一上午的python-ldap,发现要么安装vc,要么用其他比较麻烦的方法,都比较麻烦.幸好找到这个地址: http://www.lfd.uci.edu/~gohlke/pythonlibs/ ...

  3. js removeChild

    removeChild():删除元素只能通过直接父元素删除,没有自删 1 <select id="city" size="6" style="w ...

  4. VC++6.0 IDE的工程用Code::Blocks来打开、编译、调试终极配置方案

    本篇文章转自 CSDN blog,转载请注明出处! 原文地址: http://blog.csdn.net/liquanhai/article/details/6618300 引子:竟然可以用Code: ...

  5. 【LeetCode】42. Trapping Rain Water

    Trapping Rain Water Given n non-negative integers representing an elevation map where the width of e ...

  6. Linux 通过cron定期执行 php文件(转)

    Linux 通过cron定期执行 php文件 补充几点: 1. 要在php文件头加上解释器的路径,通常是 #!/usr/bin/php 2. 授予要执行的php文件执行权限   chmod a+x x ...

  7. 数据存储的两种方式:Cookie 和Web Storage

    数据存储的两种方式:Cookie 和Web Storage 1.Cookie Cookie的作用就像你去超市购物时,第一次给你办张购物卡,这个购物卡里存放了一些你的个人信息,下次你再来这个连锁超市时, ...

  8. C语言中续行符“\”说明

    把一个预处理指示写成多行要用“\”续行,因为根据定义,一条预处理指示只能由一个逻辑代码行组成. 而把C代码写成多行则不必使用续行符,因为换行在C代码中只不过是一种空白字符,在做语法解析时所有空白字符都 ...

  9. 深入浅出Node.js--数据通讯,NET模块运行机制

    互联网的运作,最根本的驱动就是信息的交互,NodeJS 在数据交互这一块做的很带感,异步编程让人很惬意,关于 NodeJS 的数据通信,最基础的两个模块是 NET 和 HTTP,前者是基于 TCP 的 ...

  10. php分页函数示例代码

    分享一例php分页函数代码,用此函数实现分页代码很不错. 代码,php分页函数. <?php /* * Created on 2011-07-28 * Author : LKK , http:/ ...