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

如何从Google Protocol Buffers工厂返回unique_ptr包装的消息?

问题:用unique_ptr管理Protobuf消息时的抽象类错误

我仍在学习使用Google Protocol Buffers库,若问题偏离主题还请见谅。我希望封装Google Proto工厂,将生成的消息类型放入unique_ptr中以避免手动内存管理。以下是我的代码:

ProtoBufFactory::ProtoBufFactory() {
    Anon::Protocol_descriptor();
    Auth::Protocol_descriptor();
    m_factory = ::google::protobuf::MessageFactory::generated_factory();
}

// 意图通过消息描述符创建Protobuf消息并用unique_ptr管理
std::unique_ptr<::google::protobuf::Message> ProtoBufFactory::create(const ::google::protobuf::Descriptor * msg_descriptor) {
    const ::google::protobuf::Message * prototype_msg = m_factory->GetPrototype( msg_descriptor );

    if (prototype_msg == nullptr) {
        EXCEPT(1, "Cannot create prototype message from message descriptor");
    }

    ::google::protobuf::Message * mutable_msg = prototype_msg->New();

    if (mutable_msg == NULL) {
        EXCEPT(1, "Failed in prototype_msg->New(); to create mutable message");
    }

    return std::make_unique<::google::protobuf::Message>(mutable_msg);
}

编译时遇到错误,提示无法操作抽象类型:

error: invalid new-expression of abstract class type ‘google::protobuf::Message’
  857 |     { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
/include/google/protobuf/message.h:235:23: note:   because the following virtual functions are pure within ‘google::protobuf::Message’:
  235 | class PROTOBUF_EXPORT Message : public MessageLite {
      |                       ^~~~~~~
/usr/local/include/google/protobuf/message.h:244:12: note:      ‘virtual google::protobuf::Message* google::protobuf::Message::New() const’
  244 |   Message* New() const override = 0;
/usr/local/include/google/protobuf/message_lite.h:465:15: note:         ‘virtual int google::protobuf::MessageLite::GetCachedSize() const’
  465 |   virtual int GetCachedSize() const = 0;
/usr/local/include/google/protobuf/message.h:367:20: note:      ‘virtual google::protobuf::Metadata google::protobuf::Message::GetMetadata() const’
  367 |   virtual Metadata GetMetadata() const = 0;

我对该错误感到困惑,曾看到类似问题是因子类未实现抽象类方法,但我已链接了C++ protobuf生成文件。我不确定该如何推进,也不确定在此场景下使用unique_ptr是否有益,希望能找到简便方法用unique_ptr管理Google Protocol Buffers消息,无需手动删除。


解决方案

错误原因

你调用std::make_unique<::google::protobuf::Message>(mutable_msg)的行为是错误的:Message是抽象基类(包含纯虚函数),无法直接实例化。而prototype_msg->New()已经返回了一个具体子类(你定义的Anon/Auth等消息类)的指针,你不需要再用make_unique去构造基类对象,只需把这个现成的指针交给unique_ptr接管即可。

修正后的代码

std::unique_ptr<::google::protobuf::Message> ProtoBufFactory::create(const ::google::protobuf::Descriptor * msg_descriptor) {
    const ::google::protobuf::Message * prototype_msg = m_factory->GetPrototype( msg_descriptor );

    if (prototype_msg == nullptr) {
        EXCEPT(1, "Cannot create prototype message from message descriptor");
    }

    ::google::protobuf::Message * mutable_msg = prototype_msg->New();

    if (mutable_msg == nullptr) {
        EXCEPT(1, "Failed in prototype_msg->New(); to create mutable message");
    }

    // 直接将子类指针交给unique_ptr,利用多态特性安全管理
    return std::unique_ptr<::google::protobuf::Message>(mutable_msg);
    // 更简洁的写法:return {mutable_msg};
}

关键说明

  1. unique_ptr的合理性:完全适合管理Protobuf消息。unique_ptr<Message>可以安全持有子类指针,且Protobuf的Message基类析构函数是虚函数,销毁时会自动调用子类的析构逻辑,不会产生内存泄漏,完美替代手动delete。
  2. 错误本质:和链接生成文件无关,是代码逻辑错误——试图实例化抽象基类,而非子类未实现方法。
  3. 额外优化:如果使用C++14及以上,也无法用make_unique直接构造抽象类实例,这里New()已经帮你创建了具体实例,直接接管指针是最优解。

内容的提问来源于stack exchange,提问作者user2267258

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 02:05:28