面试题答案
一键面试构造函数和析构函数调用过程中多态性体现
在C++中,构造函数不能是虚函数,所以在构造对象时不存在多态性。但是析构函数可以是虚函数,这在通过基类指针销毁派生类对象时会体现多态性。
当通过基类指针创建派生类对象时,首先会调用基类的构造函数,然后调用派生类的构造函数。而当通过基类指针销毁派生类对象时,如果基类的析构函数是虚函数,会先调用派生类的析构函数,然后调用基类的析构函数,这就是多态性在析构过程中的体现。
代码示例
#include <iostream>
class Base {
public:
// 虚析构函数
virtual ~Base() {
std::cout << "Base destructor" << std::endl;
}
};
class Derived : public Base {
public:
~Derived() override {
std::cout << "Derived destructor" << std::endl;
}
};
int main() {
Base* ptr = new Derived();
delete ptr;
return 0;
}
可能遇到的问题 - 内存泄漏
如果基类的析构函数不是虚函数,当通过基类指针销毁派生类对象时,只会调用基类的析构函数,而不会调用派生类的析构函数。这就可能导致派生类中分配的资源无法释放,从而造成内存泄漏。
示例如下:
#include <iostream>
class Base {
public:
// 非虚析构函数
~Base() {
std::cout << "Base destructor" << std::endl;
}
};
class Derived : public Base {
private:
int* data;
public:
Derived() {
data = new int(42);
}
~Derived() override {
std::cout << "Derived destructor" << std::endl;
delete data;
}
};
int main() {
Base* ptr = new Derived();
delete ptr;
return 0;
}
在上述代码中,Derived
类在构造函数中分配了内存,在析构函数中释放内存。但由于Base
类的析构函数不是虚函数,delete ptr
只会调用Base
类的析构函数,Derived
类的析构函数不会被调用,导致data
所指向的内存没有被释放,造成内存泄漏。
如何避免这些问题
为了避免内存泄漏问题,只要一个类有可能会被其他类继承,并且这个类的对象有可能通过基类指针来销毁,那么这个基类就应该有虚析构函数。如第一个代码示例,将Base
类的析构函数声明为虚函数,就可以保证在通过基类指针销毁派生类对象时,派生类和基类的析构函数都会被正确调用,从而避免内存泄漏。