如何在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
相关产品推荐
相关产品推荐

