引入
C++具有面向对象的特性,多态是面向对象编程的一个特性 如果基类声明了一个函数为虚函数,并且调用了指向子类的指针,如果子类确实实现了这个虚函数,结果就是调用子类中实现的虚函数
#include <iostream>
class Person {
public:
Person() {
std::cout << "Person()" << std::endl;
}
virtual void f() {
std::cout << "Person::f()" << std::endl;
}
~Person() {
std::cout << "~Person()" << std::endl;
}
};
class Student : public Person {
public:
Student() {
std::cout << "Student()" << std::endl;
}
void f() {
std::cout << "Student::f()" << std::endl;
}
~Student() {
std::cout << "~Student()" << std::endl;
}
};
int main() {
Person *p = new Student();
p->f();
delete p;
return 0;
}
输出: Person() Student() Student::f() ~Person() 将Person类指针p指向了其子类Student,因为f()被声明为虚函数,并且子类确实提供了它的实现,所以打印f(),但是,将指针p释放时并未调用子类的析构函数,并没有输出"~Student()",这是因为析构函数不是多态的,子类析构函数不被调用。(Person类的析构函数是因为delete,基类析构函数会被调用) 更改成以下代码
#include <iostream>
class Person {
public:
Person() {
std::cout << "Person()" << std::endl;
}
virtual void f() {
std::cout << "Person::f()" << std::endl;
}
virtual ~Person() {
std::cout << "~Person()" << std::endl;
}
};
class Student : public Person {
public:
Student() {
std::cout << "Student()" << std::endl;
}
void f() {
std::cout << "Student::f()" << std::endl;
}
~Student() {
std::cout << "~Student()" << std::endl;
}
};
int main() {
Person *p = new Student();
p->f();
delete p;
return 0;
}
输出: Person() Student() Student::f() ~Student() ~Person() 子类的析构函数被成功调用。
为什么要使用虚析构函数?
我们刚刚看到了没有使用虚析构函数的结果—子类析构函数不被调用。 如果我们确实想继承一个类,那么这个类应该有它自己的特性不是吗。 这样可能牵扯到数据,尤其是指针,如果子类的析构函数不被调用,子类的内部是指针的成员可能就不被释放了,造成内存泄漏。
|