C++中如何将静态运算符类实例存入map键值对?
问题分析与解决方案
你遇到的type name not allowed错误,核心原因是你试图把类类型(比如dice::Plus)直接作为map的值存入,但map需要的是类的实例(或指针),不是类型本身。同时你的设计还有两个关键问题:
- C里
static class是冗余语法,C类本身不存在“静态类”的概念,你想要的是类的实例唯一,应该用单例模式实现。 - 抽象基类
BinaryOperator不能直接实例化,map存对象会触发对象切片,丢失派生类的多态特性,必须用指针或引用存储。
解决方案:单例模式+基类指针map
通过单例模式让每个运算符类仅存在一个全局实例,再将实例的指针存入map,既满足多态调用需求,又解决了类型无法直接存入map的问题。
1. 修正类定义(实现单例)
去掉冗余的static class,将BinaryOperator设为带虚析构的抽象基类,每个运算符类通过私有构造+静态方法实现单例:
#include <map> #include <string> namespace dice { // 抽象基类:定义运算符接口 class BinaryOperator { public: int priority; virtual float apply(float left, float right) = 0; virtual ~BinaryOperator() = default; // 基类必须有虚析构,避免内存泄漏 }; // Plus运算符单例类 class Plus : public BinaryOperator { private: // 私有构造,禁止外部实例化 Plus() { priority = 1; } public: // 获取唯一实例的静态方法 static Plus& getInstance() { static Plus instance; // 局部静态变量,保证线程安全且仅初始化一次 return instance; } // 实现运算符逻辑 float apply(float left, float right) override { return left + right; } // 禁止拷贝和移动,确保实例唯一 Plus(const Plus&) = delete; Plus& operator=(const Plus&) = delete; }; // Times运算符单例类(逻辑同Plus) class Times : public BinaryOperator { private: Times() { priority = 2; } public: static Times& getInstance() { static Times instance; return instance; } float apply(float left, float right) override { return left * right; } Times(const Times&) = delete; Times& operator=(const Times&) = delete; }; // Calculator类示例 class Calculator { public: static const std::map<std::string, BinaryOperator*> str_to_op_; }; } // namespace dice
2. 初始化map
将每个单例实例的地址存入map,注意取地址符&:
const std::map<std::string, dice::BinaryOperator*> dice::Calculator::str_to_op_ = { {"+", &dice::Plus::getInstance()}, {"*", &dice::Times::getInstance()}, {"AC", &dice::AC::getInstance()}, // 假设AC类也是相同的单例实现 };
3. 调用示例(多态使用)
通过map取出指针后,直接调用虚方法apply即可实现多态:
// 获取"+"运算符实例 auto op = dice::Calculator::str_to_op_.at("+"); // 执行运算 float result = op->apply(3.0f, 5.0f); // 返回8.0f
可选优化:使用智能指针
如果担心裸指针的内存管理问题,可以用std::unique_ptr或std::shared_ptr存储实例,此时可以不用单例,直接在map初始化时创建实例:
#include <memory> const std::map<std::string, std::unique_ptr<dice::BinaryOperator>> dice::Calculator::str_to_op_ = { {"+", std::make_unique<dice::Plus>()}, {"*", std::make_unique<dice::Times>()}, {"AC", std::make_unique<dice::AC>()}, };
内容的提问来源于stack exchange,提问作者Sam F
相关产品推荐
相关产品推荐

