【学习笔记】虚函数+虚析构函数
1、虚函数
虚函数是类中使用 virtual 关键字声明的成员函数,它允许子类(派生类)重新定义(覆盖)该函数,从而在运行时根据对象的实际类型动态决定调用哪个版本的函数。
多态性是面向对象编程的三大特性之一(封装、继承、多态),指的是同一函数调用可以根据对象类型的不同,执行不同的操作。
c++
class Base {
public:
Base();
virtual ~Base();
..........
virtual int UpdataIP(MIO_JSON* pJson);
}
int Base::UpdataIP(MIO_JSON* pJson)
{
return 0;
}
Base 类中有一个虚函数 UpdataIP,但是在这个类中这个虚函数并没有实际意义。但是Hahanode以及Hehenode继承了这个类,在这两个继承类中分别对这个函数做了不一样的操作。
c++
class HahaNode : public Base {
public:
HahaNode();
~HahaNode();
int UpdataIP(MIO_JSON* pJson);
..........
}
int HahaNode::UpdataIP(MIO_JSON* pJson)
{
// 实际操作
}
class HeheNode : public Base {
public:
HeheNode();
~HeheNode();
int UpdataIP(MIO_JSON* pJson);
..........
}
int HeheNode::UpdataIP(MIO_JSON* pJson)
{
// 实际操作
}
2、虚析构函数
为什么一般将析构函数设置为虚函数。
防止内存泄漏:当基类析构函数不是虚函数时,要是通过基类指针删除派生类对象,系统只会调用基类的析构函数,而不会调用派生类的析构函数。这就可能使派生类特有的资源(像动态分配的内存、文件句柄、网络连接等)无法被释放,进而造成内存泄漏。
虚析构函数的作用:把析构函数声明为虚函数之后,在运行时会依据对象的实际类型来决定调用哪个析构函数,而不是根据指针的静态类型。这样一来,当通过基类指针删除派生类对象时,派生类的析构函数会先被调用,接着基类的析构函数也会被调用,从而确保所有资源都能被正确释放。
c++
#include <iostream>
class Base {
public:
Base() { std::cout << "Base Constructor" << std::endl; }
// 若不声明为虚函数,可能会引发问题
virtual ~Base() { std::cout << "Base Destructor" << std::endl; }
};
class Derived : public Base {
private:
int* data;
public:
Derived() {
std::cout << "Derived Constructor" << std::endl;
data = new int[100]; // 动态分配内存
}
~Derived() override {
std::cout << "Derived Destructor" << std::endl;
delete[] data; // 释放派生类资源
}
};
int main() {
Base* ptr = new Derived(); // 基类指针指向派生类对象
delete ptr; // 调用虚析构函数,确保资源正确释放
return 0;
}
结果:
c++
Base Constructor //创建基类构造函数
Derived Constructor //创建派生类构造函数
Derived Destructor //删除派生类析构函数
Base Destructor //删除基类析构函数
如果基类析构函数不是虚函数,那么delete ptr只会调用Base::~Base(),派生类的析构函数不会被调用,data所占用的内存就无法被释放。