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

如何在C++中将多个不同结构体推入单个队列?

实现方法

在C++中,要把不同类型的结构体存入同一个队列/栈,主要有以下几种可行方案:

方案一:使用std::variant(C++17及以上)

std::variant是标准库提供的类型安全联合体,可存储多种不同类型的值,适配这类场景非常直接。

代码示例

#include <queue>
#include <variant>
#include <cstdio>

struct EventRequest
{
    char EventType;
    int RetryCount;
};

struct EventStatus
{
    char EventType;
    char StatusType;
    short RetryCount;
};

// 定义包含两种事件的变体类型
using EventVariant = std::variant<EventRequest, EventStatus>;

int main()
{
    std::queue<EventVariant> q;

    EventRequest er;
    er.EventType = 'R';
    er.RetryCount = 3;
    q.push(er);

    EventStatus es;
    es.EventType = 'S';
    es.StatusType = 'D';
    es.RetryCount = 2;
    q.push(es);

    // 遍历处理队列中的事件
    while (!q.empty()) {
        auto& event = q.front();
        // 用std::visit分发不同类型的处理逻辑
        std::visit([](auto&& arg) {
            using T = std::decay_t<decltype(arg)>;
            if constexpr (std::is_same_v<T, EventRequest>) {
                printf("EventRequest: Type=%c, Retry=%d\n", arg.EventType, arg.RetryCount);
            } else if constexpr (std::is_same_v<T, EventStatus>) {
                printf("EventStatus: Type=%c, Status=%c, Retry=%d\n", arg.EventType, arg.StatusType, arg.RetryCount);
            }
        }, event);
        q.pop();
    }

    return 0;
}

说明

  • std::variant会自动管理类型信息,避免了传统union的内存安全问题。
  • 取出元素时,除了std::visit,也可以用std::holds_alternative判断当前存储的具体类型。

方案二:使用继承与多态

定义一个抽象基类,让两个事件结构体继承它,通过智能指针将子类对象存入队列,实现多态存储。

代码示例

#include <queue>
#include <memory>
#include <iostream>

// 抽象基类:统一事件接口
class BaseEvent
{
public:
    char EventType;
    // 虚析构函数保证子类对象正确销毁
    virtual ~BaseEvent() = default;
    // 纯虚函数,子类需重写实现各自的事件逻辑
    virtual void process() const = 0;
};

struct EventRequest : public BaseEvent
{
    int RetryCount;

    void process() const override
    {
        std::cout << "EventRequest: Type=" << EventType << ", Retry=" << RetryCount << std::endl;
    }
};

struct EventStatus : public BaseEvent
{
    char StatusType;
    short RetryCount;

    void process() const override
    {
        std::cout << "EventStatus: Type=" << EventType << ", Status=" << StatusType << ", Retry=" << RetryCount << std::endl;
    }
};

int main()
{
    // 队列存储基类的智能指针,避免裸指针的内存泄漏风险
    std::queue<std::unique_ptr<BaseEvent>> q;

    auto er = std::make_unique<EventRequest>();
    er->EventType = 'R';
    er->RetryCount = 3;
    q.push(std::move(er));

    auto es = std::make_unique<EventStatus>();
    es->EventType = 'S';
    es->StatusType = 'D';
    es->RetryCount = 2;
    q.push(std::move(es));

    // 遍历处理事件
    while (!q.empty()) {
        auto& event = q.front();
        event->process();
        q.pop();
    }

    return 0;
}

说明

  • 适合需要统一接口处理事件的场景,通过虚函数实现多态调用,逻辑扩展性好。
  • 使用std::unique_ptr自动管理内存,无需手动释放。

方案三:使用std::any(C++17及以上)

std::any可存储任意类型的值,灵活性高,但取出时需要手动判断类型,类型安全保障弱于std::variant。

代码示例

#include <queue>
#include <any>
#include <iostream>

struct EventRequest
{
    char EventType;
    int RetryCount;
};

struct EventStatus
{
    char EventType;
    char StatusType;
    short RetryCount;
};

int main()
{
    std::queue<std::any> q;

    EventRequest er{'R', 3};
    q.push(er);

    EventStatus es{'S', 'D', 2};
    q.push(es);

    // 遍历处理事件
    while (!q.empty()) {
        auto& event = q.front();
        // 尝试转换为对应类型,成功则处理
        if (auto* er_ptr = std::any_cast<EventRequest>(&event)) {
            std::cout << "EventRequest: Type=" << er_ptr->EventType << ", Retry=" << er_ptr->RetryCount << std::endl;
        } else if (auto* es_ptr = std::any_cast<EventStatus>(&event)) {
            std::cout << "EventStatus: Type=" << es_ptr->EventType << ", Status=" << es_ptr->StatusType << ", Retry=" << es_ptr->RetryCount << std::endl;
        }
        q.pop();
    }

    return 0;
}

说明

  • 优势是支持任意类型存储,无需预先定义类型集合,但取出时必须明确目标类型,否则std::any_cast会返回空指针(指针版本)或抛出异常(值版本)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 06:00:17