编译器如何计算' typeid '操作符

How does compiler evaluate `typeid` operator?

本文关键字:typeid 操作符 计算 何计算 编译器      更新时间:2023-10-16

这里是一些基于CRTP的模板代码,我用来尝试解决这个问题:要求覆盖的虚函数调用基实现。我会在这里发布代码,但是代码行很长,在codepad.org上更容易阅读(如果需要,我会在这里发布)。它很丑,而且有点做作,当然,尽管它确实有效。但我一开始没有意识到的是,虽然它在msvc++和GCC上都可以编译,但有些模板类型并没有真正定义。我质疑的部分是TBase::OnEvent函数顶部的几个长内部if( typeid( Derived(N) ) != typeid( Derived(N-1))(符号符号)。

你不能typdef这些类型,这将是一个编译错误-没有足够的派生类的类型来定义这样长的...::TDerived::...链,所以你会得到,正确的,编译错误TDerived is not defined in TBase。然而,编译器通过typeid吃掉了它们。当我检查调试器msvc++编译器输出(具有完整的符号信息)时,似乎所有那些长...::TDerived::...都不应该真正导致任何类,在typeid中由编译器解析为类链中的最后一个TDerived04。RTTI是为类链中的最后一个类提取的,与我有多少个...::TDerived::...无关。

考虑到msvc++和GCC都这样做(尽管我只能通过codepad.org访问GCC),我的问题是接下来:它是否以某种方式定义了typeid的行为?那么为什么...::TDerived::...中的typedef不能解析为TDerived04呢?

编辑:我的意思是,我很高兴typedef不解决TDerived04,这对任何使用typedef的人来说都是灾难,但为什么typeidtypedef之间存在这种不一致?

编辑:GCC接受TDerived04::TDerived04::TDerived04::TDerived04 lD4;变量声明。最后的类型是简单的TDerived04。是否有崩溃作用域解析的规则?显然,msvc++和GCC似乎在typeid中做同样的事情,但是msvc++,不像GCC,不能处理其他场景-它给出编译错误,需要构造函数的参数。

我不会考虑使用typeid作为除调试工具之外的任何东西。c++标准只保证它的存在,但并没有真正说明它应该做什么。这使得这个实用程序只不过是一种打印人类可读的类名的方法(如果您知道任何其他实际用途,请纠正我)。

我想说的是,typeid有太多的"编译器定义"的行为,使得它对其他任何事情都有用。

解决方案中提出的

方法也有一个巨大的缺点。除了丑陋和难以维护之外,基类还需要了解所有派生类。这是个很大的设计缺陷。

关于替代解决方案,可以在这里看到(代码也贴在原始问题中)。

至于TDerived04::TDerived04::TDerived04::TDerived04是有效的,可以解释为在TDerived04类中,您可以使用其名称TDerived04来引用该类/命名空间。所以TDerived04::TDerived04就像从TDerived04指向类TDerived04(正如@MSalters所说的,它被称为"类名注入")。

问题大致是注入的类名和构造函数名之间存在歧义。在class X的作用域中,X可以命名类本身,但X::X也可以引用构造函数,在有意义的地方。