c++里面虚函数与析构函数的关联
首先介绍一下什么是虚函数和析构函数?
虚函数定义:
在基类中用关键字virtual修饰,在派生类中进行重新定义的函数。
virtual 函数类型 函数名(形参表){
函数体;
}
虚函数的作用:
用于实现C++的多态,通过基类的指针可以访问派生类中同名的函数。
实例:
#include<iostream>
using namespace std;
class A {
public:
virtual void fun() {
cout << "this is A!" <<endl;
}
};
class B:public A {
public:
void fun() {
cout << "this is B!" <<endl;
}
};
int main() {
A *p1, *p2;
A a;
B b;
p1 = &a; //基类的指针指向基类的对象
p2 = &b; //基类的指针指向派生类的对象
p1->fun();
p2->fun();
return 0;
}
/*输出结果*/
this is A!
this is B!
析构函数的定义:
成员函数的一种,一个类只能有一个析构函数,如果没有单独定义,会默认生成。
~ 类名(){
}
析构函数的作用:
析构函数在对象消亡时会自动被调用,常常被用来用做一些对象消亡时的善后工作,比如说释放用new申请的空间。
实例:
#include <iostream>
using namespace std;
class A {
public:
~ A() {
cout <<"析构函数"<<endl;
}
};
int main() {
A *p = new A;
delete p; //delete一个对象,会调用析构函数
return 0;
}
/*输出结果*/
析构函数
析构函数与虚函数的关系?
一.为什么析构函数必须是虚函数
防止内存泄漏,假如析构函数不是用的虚函数有可能会发生内存泄漏,实例:
#include<iostream>
using namespace std;
class A {
private:
int *num_a;
public:
virtual void fun() {
cout << "this is A!" <<endl;
}
A() {
num_a = new int[10];
cout<< "A 构造" <<endl;
}
~ A() {
delete[] num_a;
cout << "A 析构" << endl;
}
};
class B:public A {
private:
int * num_b;
public:
void fun() {
cout << "this is B!" <<endl;
}
B() {
num_b = new int[10];
cout <<"B 构造"<<endl;
}
~B() {
delete num_b;
cout << "B 析构" <<endl;
}
};
int main() {
A *p1 = new B;
delete p1;
return 0;
}
/*
B b;
A *p1 = &b;
delete p1 报错
p1 不是通过new 得到新的内存空间,而是直接指向固定变量b。所以删除p1等同要强行剥夺b的固有空间,会导致出错
*/
/*输出结果*/
A 构造
B 构造
A 析构
因为析构函数不是虚函数,所以基类的指针不会调用到派生类的析构函数
这样就导致了B构造函数中的内存没有得到释放,**造成了内存泄漏**。
此时将A的析构函数改为虚函数
class A {
private:
int *num_a;
public:
virtual void fun() {
cout << "this is A!" <<endl;
}
A() {
num_a = new int[10];
cout<< "A 构造" <<endl;
}
virtual ~ A() {
delete[] num_a;
cout << "A 析构" << endl;
}
};
/*运行结果*/
A 构造
B 构造
B 析构
A 析构
这样就避免了内存泄漏
二.那默认的析构函数是不是虚函数
答案:不是
原因:因为虚函数是需要额外的虚函数表和虚表指针,会占用内存,如果用不到基类的指针调用派生类的方法,会浪费内存,所以默认的析构函数不是虚函数。