C++中如何避免对象切片,调用子类重写的Callback虚函数?
解决:父类逻辑调用子类重写的虚函数
你的问题核心是对象切片(Object Slicing):当你把PlayerListEvent对象直接存入std::vector<Event>时,子类独有的成员和虚函数表会被截断,容器里实际存储的是纯父类对象,所以调用Callback只会执行父类实现。
要触发C++的多态特性,必须通过基类指针或引用来操作子类对象,以下是两种可行的修改方案:
方案1:使用智能指针容器(推荐)
用std::unique_ptr或std::shared_ptr管理对象,避免手动内存管理的风险:
修改后的完整代码
#include <memory> #include <vector> #include <iostream> // 给Event添加虚析构函数,避免内存泄漏 class Event { public: virtual void Callback() { std::cout << "Basic Event\n"; } virtual ~Event() = default; }; class PlayerListEvent : public Event { public: std::vector<int> Players; void Callback() override { std::cout << "Player Event Processing\n"; } }; int main() { // 定义智能指针容器 std::vector<std::unique_ptr<Event>> events; // 向容器中添加子类/父类对象 events.emplace_back(std::make_unique<PlayerListEvent>()); events.emplace_back(std::make_unique<Event>()); // 遍历调用Callback,触发多态 for (const auto& event_ptr : events) { event_ptr->Callback(); } return 0; }
方案2:使用原始指针容器
如果必须用原始指针,需手动管理内存:
#include <vector> #include <iostream> // 同样需要给Event添加虚析构函数 class Event { public: virtual void Callback() { std::cout << "Basic Event\n"; } virtual ~Event() = default; }; class PlayerListEvent : public Event { public: std::vector<int> Players; void Callback() override { std::cout << "Player Event Processing\n"; } }; int main() { std::vector<Event*> events; events.push_back(new PlayerListEvent()); events.push_back(new Event()); // 调用虚函数 for (Event* e : events) { e->Callback(); } // 手动释放内存,避免泄漏 for (Event* e : events) { delete e; } events.clear(); return 0; }
关键说明
C++的虚函数多态依赖指针/引用:当通过基类指针或引用指向子类对象时,程序会在运行时根据对象的实际类型(而非指针/引用的静态类型)调用对应的虚函数版本,这样就能执行子类重写的Callback逻辑。
内容的提问来源于stack exchange,提问作者drilager60
相关产品推荐
相关产品推荐

