You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 18:54:04