在 C++ 中,使用 virtual 关键字 修饰的 函数 被称为 虚函数,C++ 的 构造函数 不可以被声明为虚函数,但 析构函数 可以被声明为虚函数,并且有时候必须将析构声明为虚函数。
用 C++ 开发的时候,用来做基类的类的析构函数一般都是虚函数。
虚析构函数是为了避免内存泄露,而且是当子类中会有指针 成员变量 时才会使用得到的。也就说虚析构函数使得在删除指向子类对象的基类指针时可以调用子类的析构函数达到释放子类中堆内存的目的,而防止内存泄露的。
当父类的析构函数不声明成虚析构函数的时候,当子类继承父类,父类的指针指向子类时,delete掉父类的指针,只调动父类的析构函数,而不调动子类的析构函数。
当父类的析构函数声明成虚析构函数的时候,当子类继承父类,父类的指针指向子类时,delete掉父类的指针,先调动子类的析构函数,再调动父类的析构函数。
virtual ~FuncName()
{}
我们将析构函数 FuncName 声明为了虚析构。
C++ 虚函数的使用
#include <iostream>
#include <cstring>
using namespace std;
//Person类
class Person
{
public:
Person(string name, int age):m_name(name),m_age(age)
{
}
virtual void info()
{
cout << "Call Person info, Name = " << this->m_name << " Age = " << this->m_age << endl;
}
~Person()
{
cout << "Call ~Person" << endl;
}
protected:
string m_name;
int m_age;
};
class Student:public Person
{
public:
Student(string name, int age, float score):Person(name, age),m_score(score)
{
}
virtual void info()
{
cout << "Call Student info, Name = " << this->m_name << " Age = " << this->m_age << " Score = " << m_score << endl;
}
~Student()
{
cout << "Call ~Student" << endl;
}
protected:
float m_score;
};
int main()
{
cout << "嗨客网(www.haicoder.net)\n" << endl;
Person *person = new Student("HaiCoder", 18, 99);
person->info();
delete person;
return 0;
}
程序运行后,控制台输出如下:
我们在 main 函数里面,使用了父类指向了子类对象,最终,我们释放子类对象时,调用了父类的析构函数,这样会导致,我们子类对象的一些数据成员没发得到释放,会造成内存泄露,现在,我们将析构修改为虚析构,修改程序如下:
#include <iostream>
#include <cstring>
using namespace std;
//Person类
class Person
{
public:
Person(string name, int age):m_name(name),m_age(age)
{
}
virtual void info()
{
cout << "Call Person info, Name = " << this->m_name << " Age = " << this->m_age << endl;
}
virtual ~Person()
{
cout << "Call ~Person" << endl;
}
protected:
string m_name;
int m_age;
};
class Student:public Person
{
public:
Student(string name, int age, float score):Person(name, age),m_score(score)
{
}
virtual void info()
{
cout << "Call Student info, Name = " << this->m_name << " Age = " << this->m_age << " Score = " << m_score << endl;
}
~Student()
{
cout << "Call ~Student" << endl;
}
protected:
float m_score;
};
int main()
{
cout << "嗨客网(www.haicoder.net)\n" << endl;
Person *person = new Student("HaiCoder", 18, 99);
person->info();
delete person;
return 0;
}
程序运行后,控制台输出如下:
这次,我们将父类的析构函数声明为了虚析构,再次运行程序,我们发现,这次首先调用了子类的析构函数,再次调用了父类的构造函数,这样就不会存在资源泄露的问题了,因此,存在继承时,最好将父类的析构声明为虚析构。
用 C++ 开发的时候,用来做基类的类的析构函数一般都是虚函数。
虚析构函数是为了避免内存泄露,而且是当子类中会有指针成员变量时才会使用得到的。也就说虚析构函数使得在删除指向子类对象的基类指针时可以调用子类的析构函数达到释放子类中堆内存的目的,而防止内存泄露的。