C++ 中 父类的虚 析构函数_legend



    C++  父类虚析构函数

 (1)C++虚函数 :


 1). C++ 多态 :

 将子类对象指针赋值给父类指针,然后通过父类指针来调用
 子类中重写的虚函数。
 如果在重写的函数不是虚函数,那么调用的还是父类的函数,
 而不是子类中重写的函数。

 2). 析构函数工作方式 :

 (  派生类的析构函数会自动调用其基类的析构函数。)

  最底层的派生类(most derived class)的析构函数最先被调用,然后调用每一个基类的析构函数。

  在C++中,当一个派生类对象通过使用一个基类指针删除,而这个基类有一个非虚的析构函数,则结果是未定义的。运行时比较有代表性的后果是对象的派生部分不会被销毁。然而,基类部分很可能已被销毁,这就导致了一个古怪的“部分析构”对象,这是一个泄漏资源。

 3). C++父类虚析构函数适用条件 :

 通过父类指针来删除子类对象时,适用父类的虚析构函数,
 保证子类的析构函数以及父类的
 析构函数都得到调用。

 一般如果不做基类的类的析构函数一般不声明为虚函数,
 因为虚函数的实现要求对象携带额外的信息.

 4)  父类中  纯虚 析构函数 的声明 与定义: (不是声明)

  1. 纯虚成员函数通常没有定义;它们是在抽象类中声明,
 然后在派生类中实现。比如说下面的例子:
  class File //an abstract class
  {
  public:
   virtual int open(const string & path, int mode=0x666)=0;
   virtual int close()=0;
  //...
  };

  2.  在某些情况下,我们却需要定义一个纯虚成员函数,而不仅仅是声明它。最常见的例子是纯虚析构函数。

  class File //abstract class
  {
  public:
   virtual ~File()=0; //declaration of a pure virtual dtor
  };
  File::~File() {} //definition of dtor

  派生类的析构函数会自动调用其基类的析构函数。这个过程是递归的,最终,抽象类的纯虚析构函数也会被调用。

  如果纯虚析构函数只被声明而没有定义,那么就会造成运行时(runtime)崩溃。
  
  纯虚析构函数的哑元实现(dummy implementation,即空实现)能够保证这样的代码的安全性。


 (2)C++中 多态时,父类虚析构函数,是为了防止调用父类析构函数,
 而不调用子类析构函数,防止内存泄露。

 (3)C++ 中,调用子类的析构函数时,先执行之类的析构函数,
 然后在执行父类的析构函数。

 范例一:

 #include
  using namespace std;
  class ClxBase{
  public:
      ClxBase() {};
      ~ClxBase() {cout << "Output from the destructor of class ClxBase!" << endl;};

      void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
  };

  class ClxDerived : public ClxBase{
  public:
      ClxDerived() {};
      ~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };

      void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };
  };
    int   main(){ 
    ClxDerived *p =  new ClxDerived;
    p->DoSomething();
    delete p;
    return 0;
    }

    运行结果:

  Do something in class ClxDerived!           

  Output from the destructor of class ClxDerived!

  Output from the destructor of class ClxBase! 
在main函数中用继承类的指针去操作继承类的成员,
释放指针P的过程是:先释放继承类的资源,再释放基类资源.


范例二:


#include
using namespace std;
class ClxBase{
public:
    ClxBase() {};
    ~ClxBase() {cout << "Output from the destructor of class ClxBase!" << endl;};

    void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};

class ClxDerived : public ClxBase{
public:
    ClxDerived() {};
    ~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };

    void DoSomething() { cout << "Do something in class ClxDerived!" << endl; }
};
  int   main(){ 
  ClxBase *p =  new ClxDerived;
  p->DoSomething();
  delete p;
  return 0;
  }

输出结果:

  Do something in class ClxBase!
  Output from the destructor of class ClxBase!

在main函数中用基类的指针去操作继承类的成员,释放指针P的过程是:只是释放了基类的资源,而没有调用继承类的析构函数.调用  dosomething()函数执行的也是基类定义的函数.

    一般情况下,这样的删除只能够删除基类对象,而不能删除子类对象,形成了删除一半形象,造成内存泄漏.


    范例三:

    #include
using namespace std;
class ClxBase{
public:
    ClxBase() {};
    virtual ~ClxBase() {cout << "Output from the destructor of class ClxBase!" << endl;};
    virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};

class ClxDerived : public ClxBase{
public:
    ClxDerived() {};
    ~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };
    void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };
};

  int   main(){ 
  ClxBase *p =  new ClxDerived;
  p->DoSomething();
  delete p;
  return 0;
  }

  运行结果:

  Do something in class ClxDerived!
  Output from the destructor of class ClxDerived!
  Output from the destructor of class ClxBase!

范例四:
#include

class Base
{
public:
    Base() {data = new char[64]; }
    ~Base(){delete [] data;}
private:
    char *data;
};

class BaseEx: public Base
{
public:
    BaseEx(){m_data = new char[64];}
    ~BaseEx(){delete [] m_data;}
private:
    char *m_data;
    // 子类中又定义的成员。
};

void main()
{
Base*pCBase = new BaseEx;
delete pCBase ;
}

很显然,上述的程序有内存泄漏。这是因为当删除pCBase时,
它只调用了Base的析构函数而没调用BaseEx的析构函数,
所以导致内存泄漏。

你可能感兴趣的:(C++,父类虚析构函数)