#include <iostream>
// 基类
class Base {
public:
virtual void virtualFunction1() {
std::cout << "Base::virtualFunction1" << std::endl;
}
virtual void virtualFunction2() {
std::cout << "Base::virtualFunction2" << std::endl;
}
};
// 中间派生类
class Middle : public Base {
public:
void virtualFunction1() override {
std::cout << "Middle::virtualFunction1" << std::endl;
}
};
// 最终派生类
class Final : public Middle {
public:
void virtualFunction2() override {
std::cout << "Final::virtualFunction2" << std::endl;
}
};
int main() {
Base* basePtr1 = new Middle();
Base* basePtr2 = new Final();
basePtr1->virtualFunction1();
basePtr1->virtualFunction2();
basePtr2->virtualFunction1();
basePtr2->virtualFunction2();
delete basePtr1;
delete basePtr2;
return 0;
}
C++ 指针实现多态的原理
- 虚函数表:当类中定义了虚函数,C++ 编译器会为该类生成一个虚函数表(vtable)。虚函数表是一个存储类成员函数指针的数据结构。每个包含虚函数的类都有自己的虚函数表。
- 虚指针:每个对象都会包含一个指向其所属类虚函数表的指针(vptr)。当通过基类指针调用虚函数时,程序会首先根据指针指向的对象的 vptr 找到对应的虚函数表,然后在虚函数表中找到被调用虚函数的地址,并执行该函数。这样就实现了根据对象实际类型来调用相应的虚函数,即多态。
对象生命周期管理注意事项
- 动态内存分配与释放:如果使用
new
来创建对象,必须使用 delete
来释放内存,如上述代码中 delete basePtr1;
和 delete basePtr2;
。否则会导致内存泄漏。
- 智能指针:为了更好地管理对象生命周期,可以使用智能指针(如
std::unique_ptr
、std::shared_ptr
)。智能指针会在其作用域结束时自动释放所管理的对象,避免手动调用 delete
可能带来的错误。例如:
#include <memory>
//...
std::unique_ptr<Base> basePtr1 = std::make_unique<Middle>();
std::unique_ptr<Base> basePtr2 = std::make_unique<Final>();
// 智能指针会在离开作用域时自动释放对象
- 析构函数:在类体系中,基类的析构函数应该声明为虚函数。这样当通过基类指针删除派生类对象时,会先调用派生类的析构函数,再调用基类的析构函数,确保所有资源都被正确释放。例如:
class Base {
public:
virtual ~Base() {}
// 其他虚函数...
};