如何调用vector<A>中存储的子类对象的重写foo函数?
解决C++中基类容器调用子类重写函数的问题
你碰到的是C++里经典的**对象切片(Object Slicing)**问题——当你把AA/AB这类子类对象直接存入vector<A>时,容器只会拷贝基类A的部分,子类特有的数据和重写的foo()逻辑都被"切掉"了,所以调用时自然只会执行基类的空实现。
要解决这个问题,核心是避免对象切片,同时确保多态机制生效,具体可以按以下步骤来:
关键前提:基类函数必须声明为虚函数
首先要修正基类A的定义,把foo()声明为虚函数——这是C++实现运行时多态的基础,告诉编译器要根据实际对象的类型来调用对应的函数:
class A { public: // 声明为虚函数,允许子类重写 virtual void foo() {} // 基类必须添加虚析构函数,避免通过基类指针删除子类对象时内存泄漏 virtual ~A() = default; };
解决方案:使用智能指针容器
不要直接存A类型的对象,改用智能指针(比如std::unique_ptr或std::shared_ptr)来存储指向子类对象的指针,这样既不会发生对象切片,还能自动管理内存,避免手动释放的麻烦。
完整代码示例:
#include <vector> #include <memory> class A { public: virtual void foo() {} virtual ~A() = default; }; class AA : public A { public: // 使用override关键字显式标记重写,让编译器帮你检查是否正确重写了基类虚函数 void foo() override { // 子类AA的自定义实现 // 比如:std::cout << "AA's foo called\n"; } }; class AB : public A { public: void foo() override { // 子类AB的自定义实现 // 比如:std::cout << "AB's foo called\n"; } }; class C { private: // 存储智能指针的容器,指向A的子类对象 std::vector<std::unique_ptr<A>> objects; public: // 添加对象的方法,接收unique_ptr并转移所有权 void addObject(std::unique_ptr<A> obj) { objects.push_back(std::move(obj)); } // 遍历容器调用所有对象的foo() void callAllFoo() { for (auto& ptr : objects) { ptr->foo(); // 此时会根据实际子类类型调用对应的foo() } } }; // 使用示例 int main() { C c; // 用make_unique创建子类对象,传入C的容器 c.addObject(std::make_unique<AA>()); c.addObject(std::make_unique<AB>()); c.callAllFoo(); // 会依次执行AA和AB的foo()实现 return 0; }
补充说明
- 如果不想用智能指针,也可以用原始指针,但需要手动管理内存(记得在容器销毁时逐个delete),风险较高,不推荐。
- 不要尝试用
vector<A&>直接存引用——C++的vector不支持存储引用类型,虽然可以用std::reference_wrapper绕开,但需要保证被引用的对象生命周期长于容器,容易出问题,不如智能指针稳妥。
内容的提问来源于stack exchange,提问作者H. Din
相关产品推荐
相关产品推荐

