C++如何调用存储在vector中智能指针指向的子类重写方法
问题原因
你当前代码的核心问题是发生了对象切片(Object Slicing):
- 你调用
std::make_shared<Foo>(Foo1{})时,是先创建了一个Foo1临时对象,再以它为参数构造一个Foo类型的堆对象,子类独有的内容在这个过程中被完全切掉,最终vector里存储的全部都是父类Foo的实例,自然只会调用父类的Update方法。 - 额外隐患:父类
Foo没有定义虚析构函数,当智能指针释放对象时只会调用父类析构函数,子类资源会泄漏。
最优解法
直接构造对应子类类型的智能指针,利用多态的向上转型特性自动转为std::shared_ptr<Foo>存入vector即可,同时补充父类的虚析构函数。
修改后的完整代码如下:
#include <iostream> #include <memory> #include <vector> class Foo { public: virtual void Update(){ std::cout << "Update idle" << std::endl; }; // 补充虚析构函数,避免资源泄漏 virtual ~Foo() = default; }; class Foo1 : public Foo { public: void Update() override { std::cout << "Update Foo1" << std::endl; } }; class Foo2 : public Foo { public: // 调整Update权限为public,否则外部无法调用 void Update() override { std::cout << Bar() << std::endl; } private: std::string Bar(){ return "Update Foo2"; } }; int main() { std::vector<std::shared_ptr<Foo>> vec{ std::make_shared<Foo>(), std::make_shared<Foo1>(), // 直接构造Foo1实例,自动向上转型为shared_ptr<Foo> std::make_shared<Foo2>() // 直接构造Foo2实例,自动向上转型为shared_ptr<Foo> }; for (auto &&ptr : vec) { ptr->Update(); } }
修改后运行输出为:
Update idle Update Foo1 Update Foo2
补充说明
原代码中Foo2的Update是类默认private权限,外部调用会编译报错,因此解法中补充了public权限声明。如果不需要修改父类默认的析构逻辑,直接用virtual ~Foo() = default;声明虚析构即可,不需要额外写实现。
内容的提问来源于stack exchange,提问作者DeerFreak
相关产品推荐
相关产品推荐

