c 语言中析构函数,详解C++中的析构函数

简介

析构函数(Destructors),是对象的成员函数,没有返回值也没有参数,且一个类只有一个析构函数,当对象被销毁的时候调用,被销毁通常有这么几个情况。

函数执行结束

程序执行结束

程序块包含的局部变量

delete操作

什么时候要自己写析构函数?

编译器会自动创建默认的析构函数,通常都没有问题,但是当我们在类中动态分配了内存空间时,我们需要手段的回收这块空间,防止内存溢出。就像这样

class String

{

private:

char *s;

int size;

public:

String(char *); // constructor

~String(); // destructor

};

String::String(char *c)

{

size = strlen(c);

s = new char[size+1];

strcpy(s,c);

}

String::~String()

{

delete []s;

}

私有的析构函数

可以将析构函数的访问权限设置为private,设置时没有问题的,但是一个问题就是,通常的手段就没法调用析构函数了。

如下所示,程序结束后要调用析构函数,但是析构函数时私有的没法调用,所以会编译出错。

#include

using namespace std;

class Test {

private:

~Test() {}

};

int main()

{

Test t;

}

以下这样不会有问题,因为没有对象被建立,也不用析构

int main()

{

Test* t;

}

以下这样也不会有问题,因为动态分配的内存需要程序员手段释放,所以程序结束时没有释放内存,也没有调用析构函数。这里插一句,动态分配的内存如果不手动释放,程序结束后也会不会释放,但是现代操作系统可以帮我们释放,因为这个动态分配的内存和这个进程有关,操作系统应该可以捕获到这个泄露的内存从而释放。(查资料看到的)

int main()

{

Test* t = new Test;

}

如果使用delete来删除对象,会编译出错

int main()

{

Test* t = new Test;

delete t;//编译出错,无法调用私有的析构函数

}

可以利用Friend函数,进行对象的销毁,因为Friend可以访问私有成员,所以可以访问析构函数。

#include

class Test {

private:

~Test() {}

friend void destructTest(Test*);

};

void destructTest(Test* ptr)

{

delete ptr;

}

int main()

{

Test* ptr = new Test;

destructTest(ptr);

return 0;

}

或者给类写一个销毁的方法,在需要销毁的时候调用。

class Test {

public:

destroy(){delete this};

private:

~Test() {}

};

那么什么时候需要使用私有的析构函数呢?当我们只希望动态分配对象空间(在堆上)时候,用私有析构,就防止了在栈上分配,因为在编译阶段就会出错。

虚析构函数

当类用到多态的特性时候,使用虚析构函数。看如下的例子。

#include

using namespace std;

class Base

{

public:

Base(){

cout << "Base Constructor Called\n";

}

~Base(){

cout << "Base Destructor called\n";

}

};

class Derived1: public Base

{

public:

Derived1(){

cout << "Derived constructor called\n";

}

~Derived1(){

cout << "Derived destructor called\n";

}

};

int main()

{

Base *b = new Derived1();

delete b;

}

例子里的析构函数都不是虚函数,当我们想用基类的指针来删除派生类对象的时候,就出现了问题,“undefined behavior”,c++标准里规定,只由编译器实现,通常这时不会报错,会调用基类的析构函数。但这应该不是我们想要的,这会导致内存泄漏。所以要把析构函数置为虚函数。(msvc似乎不用给析构函数加virtual,默认就是虚的,gcc没有默认还是要加的)

另外虚析构函数可以是纯虚析构函数,但是要提供函数体,不然没法析构,因为虚析构函数和一般的虚函数的overide还不一样,虚析构函数要挨个执行,不提供函数体,会编译出错。

析构函数的执行顺序

派生类,成员对象,基类这样

class B

{public: virtual ~B(){cout<

};

class D

{public:virtual ~D(){cout<

} ;

class E

{public:virtual ~E(){cout<

} ;

class A

{public:virtual ~A(){cout<

};

class C:public A,B

{

public:virtual ~C(){cout<

private:

E e;

D d;

};

int main()

{

C *c;

c=new C();

delete c;

}

结果为

派生类执行了

成员D执行了

成员E执行了

基类B执行了

基类A执行了

参考

以上就是详解C++中的析构函数的详细内容,更多关于C++ 析构函数的资料请关注脚本之家其它相关文章!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值