C++中typeid.name返回派生类类型前带数字的原因及稳定性咨询
嘿,这个问题我之前做项目时也踩过坑,咱们把它拆解开来说清楚:
为什么
typeid(*question).name()会返回带数字前缀的字符串? 那个前缀数字其实是类名的字符长度,比如13QSingleChoice里的13,就是QSingleChoice这个字符串的总字符数(你数一下:Q、S、i、n、g、l、e、C、h、o、i、c、e,刚好13个)。这是C++编译器对类型名进行“名字粉碎(name mangling)”时的一种实现方式,用来辅助编译器处理重载、模板等复杂场景。
这个前缀能保证始终不变吗?
完全不能!甚至可以说,依赖这个返回值的格式是非常危险的:
- 同一台电脑上,换个编译器版本、调整编译选项(比如开启优化、修改名字粉碎规则),前缀都可能变化;
- 换不同的编译器(比如Windows用MSVC,Linux用GCC,Mac用Clang),返回的格式差异会更大——有的可能不是数字前缀,甚至会返回完全不同的标识字符串(比如你担心的"ASDQSingleChoice"这种情况,虽然极端,但标准没限制编译器的实现方式,理论上是有可能的)。
靠谱的替代方案
既然typeid().name()的返回值不可靠,推荐用以下两种更可控的方式来判断题型:
- 自定义纯虚函数返回类型字符串:在抽象基类
Question里添加一个纯虚函数:
然后每个派生类重写这个函数,返回明确的类型名:class Question { public: virtual ~Question() = default; // 记得加虚析构函数避免内存泄漏 virtual std::string getQuestionType() const = 0; };
这种方式完全由你控制,不会有任何歧义。class QSingleChoice : public Question { public: std::string getQuestionType() const override { return "QSingleChoice"; } }; - 用枚举类型判断:如果不想用字符串,还可以定义枚举类型来标识题型:
这种方式类型更安全,还能避免字符串拼写错误的问题。class Question { public: enum class Type { SingleChoice, MultipleChoice, Text, Ordering }; virtual ~Question() = default; virtual Type getQuestionType() const = 0; }; class QSingleChoice : public Question { public: Type getQuestionType() const override { return Type::SingleChoice; } };
内容的提问来源于stack exchange,提问作者skluzada
相关产品推荐
相关产品推荐

