什么时候需要将析构函数定义为虚函数,如果不这么做,会存在什么问题?

这是网易游戏面我的一道题,当时想了一想,结果答错了,没在意,今天测试了一下,结果才认识到问题所在!

直接看代码:

class Interface {
public:
    virtual void fun() = 0;
    Interface() {
        cout<<"Interface::Interface()"<<endl;
        _data = new char[10];
    }
    virtual ~Interface() {
        cout<<"Interface::~Interface()"<<endl;
        delete [] _data;
    }
protected:
    char *_data;
};

class Implement: public Interface {
public:
    void fun() {
        cout<<"This is Implement object."<<endl;
    }

    Implement() {
        cout<<"Implement::Implement()"<<endl;
        _ba = new char[10];
    }

    ~Implement() {
        cout<<"Implement::~Implement()"<<endl;
        delete []_ba;
    }
private:
    int a;
    char *_ba;
};

下面,我们来分析一下问题所在:

1)如果基类(Interface)的析构函数不为虚函数

//内存泄露(子类析构函数没有被调用)
    Interface *base = new Implement();
    delete base;

base则找不到子类的析构函数,因此,只调用了父类自身的析构函数,因此造成内存泄露;

2)如果基类(Interface)的析构函数为虚函数,那么虚函数表就会多了一个函数指针,这个函数指针方便了base找到正确的析构函数(子类Implement析构函数),而子类的析构函数会自动调用基类(Interface)的析构函数,这样子,全部内存都被回收!

时间: 2024-10-10 11:14:47

什么时候需要将析构函数定义为虚函数,如果不这么做,会存在什么问题?的相关文章

析构函数定义为虚函数原因

析构函数定义为虚函数原因 先看下面一段程序: #include <iostream> using namespace std; class Person { public: virtual ~Person()                    //加了virtual,讲析构函数声明为虚函数 {    cout << "Person::~Person()" << endl; } }; class Student : public Person {

为什么有时候需要把析构函数定义为虚函数

为什么有时候需要把析构函数定义为虚函数 析构函数的作用是在对象撤销之前做必要的清理现场的工作,当派生类的对象从内存中撤销时一般先调用派生类的析构函数,然后在调用基类的析构函数,但是用new运算符建立了一个派生类对象,并且把他赋给基类指针,那么当用delete运算符撤销这个指针指向的存储空间的时候,系统会只执行基类的析构函数,而不执行派生类的析构函数.

C++中为什么要将析构函数定义成虚函数

构造函数不可以是虚函数的,这个很显然,毕竟虚函数都对应一个虚函数表,虚函数表是存在对象内存空间的,如果构造函数是虚的,就需要一个虚函数表来调用,但是类还没实例化没有内存空间就没有虚函数表,这根本就是个死循环. 可是析构函数却要定义成虚函数,这是为什么呢,写一个非常简单的例子来理解一下: class AA { public: AA() {}; ~AA() { fun2(); }; virtual void fun1() { cout << "Base construct" &

从为什么要将基类的析构函数定义为虚函数谈起~~

 首先,做一个最简单的实验,在电脑上运行下面的代码,将会产生运行错误,这或许会使你百思不得其解: #include <iostream> using namespace std; class Base { private: int a; public: ~Base(){cout << "Base dtor..." << endl;} }; class Derived : public Base { private: int b; public: ~D

析构函数定义为虚函数

析构函数执行时先调用派生类的析构函数,其次才调用基类的析构函数.如果析构函数不是虚函数,而程序执行时又要通过基类的指针去销毁派生类的动态对象,那么用delete销毁对象时,只调用了基类的析构函数,未调用派生类的析构函数.这样会造成销毁对象不完全. #include<iostream.h> #include<stdlib.h> class CPerson { public: virtual ~CPerson(); //基类的析构函数必须声明为虚函数,否则 用delete销毁对象时会出

C++ Primer 学习笔记33_面向对象编程(4)--虚函数与多态(一):多态、派生类重定义、虚函数的访问、 . 和-&gt;的区别、虚析构函数、object slicing与虚函数

C++ Primer学习笔记33_面向对象编程(4)--虚函数与多态(一):多态.派生类重定义.虚函数的访问. . 和->的区别.虚析构函数.object slicing与虚函数 一.多态 多态可以简单地概括为"一个接口,多种方法",前面讲过的重载就是一种简单的多态,一个函数名(调用接口)对应着几个不同的函数原型(方法). 更通俗的说,多态行是指同一个操作作用于不同的对象就会产生不同的响应.或者说,多态性是指发出同样的消息被不同类型的对象接收时有可能导致完全不同的行为. 多态行分

虚析构函数与纯虚函数

虚析构函数 通过基类的指针删除派生类对象时,通常情况只调用基类的析构函数 但是,删除一个派生类对象时,应该先调用派生类的析构函数,然后调用基类的析构函数(构造时自顶向下,析构时自底向上) 这种情况会产生内存泄漏,最终导致系统应可用内存不足而崩溃 解决办法 把基类的析构函数声明为virtual,此时派生类的析构函数即使不声明为virtual也为virtual函数 在调用基类的指针删除派生类对象时,会先调用派生类的析构函数,最后调用基类的析构函数 一般方法 如果一个类定义了虚函数,那么析构函数也应该

析构函数什么情况下要定义为虚函数?

原文出处:点击我:) 1.第一段代码 #include<iostream>using namespace std;class ClxBase{public:    ClxBase() {};    ~ClxBase() {cout << "Output from the destructor of class ClxBase!" << endl;}; void DoSomething() { cout << "Do someth

第八章:不要在构造和析构函数中使用虚函数

前言 本文将讲解一个新手C++程序员经常会犯的错误 - 在构造/析构函数中使用虚函数,并分析错误原因所在以及规避方法. 错误起因 首先,假设我们以一个实现交易的类为父类,然后一个实现买的类,一个实现卖的类为其子类. 这三个类的对象初始化过程中,都需要完成注册的这么一件事情 (函数).然而,各自注册的具体行为是不同的. 有些人会写出以下这样的代码: 1 class Transaction { 2 public: 3 Transaction(); // 父类构造函数 4 //...... 5 pri