1

这是我用来尝试解决这个问题的一些基于 CRTP 的模板代码: 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::...不应该真正导致任何类的 long 都typeid被编译器解析为TDerived04类链中的最后一个。...::TDerived::...并且 RTTI 被拉到班级链中的最后一个班级,与我有多少无关。

考虑到 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++ 无法处理其他情况——它会产生编译错误,需要构造函数的参数。

4

2 回答 2

1

问题大致是注入的类名和构造函数名之间存在歧义。在 的范围内class XX可以命名类本身,但X::X也可以引用构造函数——这很有意义

于 2012-01-03T11:53:33.243 回答
1

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

我会说有太多的“编译器定义”行为typeid使其对上述以外的任何东西都有用。

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

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

至于TDerived04::TDerived04::TDerived04::TDerived04是否有效,可以通过 TDerived04 类中的说明来解释,您可以使用其名称 TDerived04 来引用此类/命名空间。所以 TDerived04::TDerived04 就像从 TDerived04 指向类 TDerived04 (正如@MSalters所说的那样,它被称为“类名注入”)。

于 2012-01-04T09:53:56.123 回答