这是我用来尝试解决此问题的一些CRTP based template code:Requiring overridden virtual functions to call base implementations。我会在这里发布代码,但是这些行很长,并且更容易在codepad.org上阅读(如果需要,我会在这里发布)。尽管确实有效,但它很丑陋,而且有些人为。但是我一开始并没有意识到,虽然它可以在MSVC++和GCC上进行编译,但实际上并没有定义某些模板类型。我要询问的部分是顶部if( typeid( Derived(N) ) != typeid( Derived(N-1))函数中的几个较长的内部TBase::OnEvent(符号表示法)。

您不能typdef这些类型,这将是一个编译错误-这么长的...::TDerived::...链根本没有足够的派生类来定义类型,因此您会正确地获得编译错误TDerived is not defined in TBase。但是编译器通过typeid吞噬了它们。当我检入调试器MSVC++编译器输出(带有完整的符号信息)时,似乎所有那些不应真正导致任何类的长...::TDerived::...,在typeid中由编译器解析为类链中的最后一个TDerived04。而RTTI在类链中的最后一个类中被拉出,与我拥有的...::TDerived::...数量无关。

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

编辑:我是说,我很高兴typedef不能解析为TDerived04,对于使用typedef的任何人来说都是灾难,但是为什么typeidtypedef之间如此不一致?

编辑:GCC接受TDerived04::TDerived04::TDerived04::TDerived04 lD4;变量声明。最后,类型只是TDerived04。是否有折叠示波器分辨率的规则?显然,MSVC++和GCC在typeid中似乎做的相同,但与GCC不同,MSVC++无法处理其他情况-它会产生编译错误,需要构造函数使用参数。

最佳答案

除了调试工具之外,我不会考虑将typeid用作其他任何工具。 C++标准仅保证其存在,而没有真正说出应该做什么。这使得这种实用性不过是打印人类可读的类名的一种方式(如果您知道任何其他实际用途,请更正我)。

我要说的是typeid的“编译器定义”行为太多,因此无法用于除上述之外的任何其他事情。

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

至于替代解决方案,可以看到here(代码也发布在原始问题中)。

至于TDerived04::TDerived04::TDerived04::TDerived04是有效的,可以用TDerived04类中的类来说明,您可以使用其名称TDerived04来引用此类/命名空间。因此TDerived04::TDerived04就像从TDerived04指向类TDerived04(@MSalters称其为“类名注入(inject)”)。

关于c++ - 编译器如何评估 `typeid`运算符?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8711184/

10-09 06:37