c++ 虚函数与析构函数

文章讨论了C++中构造函数和析构函数的特性,特别是析构函数为何必须可以是虚的,以防止内存泄漏。构造函数总是先调用基类的构造函数,然后是派生类的。而析构函数的调用顺序相反。纯虚析构函数使得基类成为抽象类,不允许实例化。文章还提到了动态类型转换和虚函数在确保正确析构多态对象中的作用。
摘要由CSDN通过智能技术生成

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

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

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

#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是否一致

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值