C++使用存储抽象类unique_ptr的vector时vtable编译错误求助
问题根因
你遇到的vtable相关报错完全来自抽象类的语法错误,和用vector存储抽象类unique_ptr的方案无关,该方案是C++实现多态集合的标准合理写法,完全符合你的需求。
报错的两个核心原因:
- 纯虚析构函数必须提供实现:和普通纯虚函数不同,子类析构时会自动调用父类析构函数,哪怕父类析构是纯虚的也必须有实现,否则链接时会找不到虚函数表中对应的析构地址,触发vtable相关错误。
- 未给虚函数
stub()提供实现也未声明为纯虚:Abstract类中声明的virtual bool stub();没有函数体,也没有标记为=0的纯虚属性,编译器生成虚函数表时找不到该函数的入口地址,导致链接失败。
修复后的完整代码
#include <iostream> #include <vector> #include <memory> class Abstract { protected: int capacity; public: int getCapacity() { return capacity; } // 纯虚析构函数声明 virtual ~Abstract() = 0; // 声明为纯虚函数,让Abstract成为不可实例化的抽象类 virtual bool stub() = 0; }; // 纯虚析构函数的实现(必须提供) Abstract::~Abstract() = default; class Specific : public Abstract { public: Specific() { capacity = 9; } bool stub() override { // 建议加override关键字显式标记重写 return false; } }; // 补充第二个子类,符合你的需求 class AnotherSpecific : public Abstract { public: AnotherSpecific() { capacity = 18; } bool stub() override { return true; } }; class Test { public: std::vector<std::unique_ptr<Abstract>> vec; void addIt(std::unique_ptr<Abstract> thing) { vec.push_back(std::move(thing)); } }; int main() { Test t; // 存入第一个子类实例 std::unique_ptr<Specific> testPtr(new Specific()); t.addIt(std::move(testPtr)); // 存入第二个子类实例,验证混合存储能力 std::unique_ptr<AnotherSpecific> anotherPtr(new AnotherSpecific()); t.addIt(std::move(anotherPtr)); // 测试多态调用 for (auto& ptr : t.vec) { std::cout << "capacity: " << ptr->getCapacity() << ", stub return: " << ptr->stub() << std::endl; } return 0; }
方案验证
修复后完全满足你的设计需求:
- Abstract类因为包含纯虚函数,无法直接实例化,两个子类都实现了所有纯虚函数,可以正常实例化
- 用
unique_ptr管控实例所有权,移动语义保证同一时间只有一份实例拷贝,vector可以正常混合存储两个子类的实例指针,多态调用正常。
内容的提问来源于stack exchange,提问作者CalebK
相关产品推荐
相关产品推荐

