c++ 虚函数与析构函数

  • Post author:
  • Post category:其他


构造函数是不能为虚函数的,但析构函数能够且常常必须是虚的。

构造函数,先调用基类的构造函数,其次调用更晚的派生类的构造函数。

析构函数和构造函数的顺序相反。

#include<iostream>
using namespace std;
class Base1
{
public:
    ~Base1(){
        cout<<"~Base1()\n";
    }
};

class Derived1:public Base1
{
public:
   ~Derived1(){
    cout<<"~ Derived1"<<endl;
   }
};
class Base2
{
public:
    virtual ~Base2(){
        cout<<"~Base2()\n";
    }
};
class Derived2:public Base2
{
public:
   ~Derived2(){
    cout<<"~ Derived2"<<endl;
   }
};

int main()
{
    Base1* bp = new Derived1;
    delete bp;
    Base2* bp2 =new Derived2;
    delete bp2;
}

~Base1()

~ Derived2

~Base2()

delete bp只调用基类的析构函数 。

delete bp2 调用了派生类的析构函数。

析构函数是虚函数,可以避免内存泄漏的问题。

纯虚析构函数

纯虚构函数必须是合法的,且在实用时,有一个限制,必须为纯虚函数提供一个函数体。

为什么?析构函数总要按顺序进行调用,如果没有实体,调用什么呢?

纯虚构函数和虚构函数的区别是什么:

纯虚构函数使基类是抽象类,抽象类,不可以创建对象。

从某个含有虚析构函数的类中,继承一个类,不向其它纯虚函数,我们不要求在派生类中提供纯虚函数的定义。因为编译器会自动生成虚构函数。

#include<iostream>
using namespace std;
class Base
{
public:
   virtual ~Base() = 0;
};
class Derive:public Base
{}
int main()
{

}

不会出现编译错误。

当我们类中,仅含有一个纯虚函数:

析构函数的纯虚性,唯一效果可以阻止基类的实例化。

如果有其他纯虚构函数将会执行这一操作,所以当虚析构函数是十分必要的,它是不是存虚的就没有那么重要。

#include<iostream>
using namespace std;
class Base
{
public:
   virtual ~Base() = 0;
};
Base::~Base()
{
    cout<<"~ Base"<<endl;
}
class Derive:public Base
{};
int main()
{
   Base *p = new Derive;
   delete p;
}

~ Base

可以看到,基类的纯虚构函数会被调用。



作为一个准则,任何时候,我们的类中,都要有一个虚函数,我们应当增加一个虚析构函数,即使我们什么都不做。

析构函数的虚机制

using namespace std;
class Base
{
public:
   virtual ~Base();
   virtual void  f(){
    cout<<"Base f function\n";
   }
};
Base::~Base()
{
    cout<<"~ Base"<<endl;
    f();
}
class Derive:public Base
{
public:
   ~Derive(){
    cout<<"~ Derive"<<endl;   
   };
   void f(){
    cout<<"Derive f function\n";
   }


};
int main()
{
   Base *p = new Derive;
   delete p;
}

~ Derive

~ Base

Base f functio



在虚析构函数中调用函数,无论被调用的函数是否是虚析构函数,调用的都是本地的函数。

向下类型转换

#include<iostream>
using namespace std;
class Base
{
public:
   virtual ~Base(){}
};
class Derive:public Base
{
public:
   ~Derive(){
   };
};
class Derive2:public Base
{
public:
   ~Derive2(){
   };
};
int main()
{
   Base *p = new Derive;
   Derive *pD = dynamic_cast<Derive *>(p);
   Derive2 *pD2 = dynamic_cast<Derive2 *>(p);
   cout<<"pD = "<<(long)pD<<endl;
   cout<<"pD2 = "<<(long)pD2<<endl;
}

pD = 27020320

pD2 = 0

#include<iostream>
using namespace std;
class Base
{
public:
   virtual ~Base(){}
};
class Derive:public Base
{
public:
   ~Derive(){
   };
};
class Derive2:public Base
{
public:
   ~Derive2(){
   };
};
int main()
{
   Base *p = new Derive;
   Derive *pD = dynamic_cast<Derive *>(p);
   Derive2 *pD2 = dynamic_cast<Derive2 *>(p);
   cout<<"pD = "<<(long)pD<<endl;
   cout<<"pD2 = "<<(long)pD2<<endl;
   //使用Dynamic 需要判空
   Derive * pD3 = nullptr;
   Derive2 * pD4 = nullptr;
   if(typeid(pD3) == typeid(p))
   {
      pD3 = static_cast<Derive*> p;
   }
   
   //使用static_cast 可以先判断typeid是否一致

}



版权声明:本文为SYY_LR原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。