【发布时间】:2011-11-11 13:43:52
【问题描述】:
我正在考虑使用 typeid 来解析类型的类型擦除设置...
struct BaseThing
{
virtual ~BaseThing() = 0 {}
};
template<typename T>
struct Thing : public BaseThing
{
T x;
};
struct A{};
struct B{};
int main()
{
BaseThing* pThing = new Thing<B>();
const std::type_info& x = typeid(*pThing);
if( x == typeid(Thing<B>))
{
std::cout << "pThing is a Thing<B>!\n";
Thing<B>* pB = static_cast<Thing<B>*>(pThing);
}
else if( x == typeid(Thing<A>))
{
std::cout << "pThing is a Thing<A>!\n";
Thing<A>* pA = static_cast<Thing<A>*>(pThing);
}
}
我从未见过其他人这样做。另一种方法是让 BaseThing 拥有一个纯虚拟 GetID() 来推断类型,而不是使用 typeid。在这种情况下,只有 1 级继承,typeid 的成本与虚函数调用的成本是多少?我知道 typeid 以某种方式使用 vtable,但它究竟是如何工作的?
这将是可取的,而不是 GetID(),因为要确保 ID 是唯一的和确定性需要相当多的技巧。
【问题讨论】:
-
最初,虚拟继承旨在避免您在 main 函数中使用的那种 switch 或 if-else-chain。如果有人忘记添加 else,这个开关很容易出错。您是否完全确定虚拟分派或双重分派不会在您的情况下完成这项工作?
-
Boost.Any 使用
typeid(与static_cast结合使用)好吧。用户代码使用get函数,并且不打扰typeid。 - 实际上,您最好使用它,而不是自己滚动,因为它为您做的更多(克隆和管理动态内存)。 -
@thiton 考虑一下当今世界上的大多数事件处理程序方法 - 它们几乎都具有与上述等效的 switch 或 if/else 链。
-
@visitor Boost.Any 看起来很完美,除了它没有针对右值引用进行更新,它可以从 make_any 中受益,就像 shared_ptr 有一个 make_shared 一样,并且 any_cast 不能正确替换 dynamic_cast(见下面 celtschk 的回答为什么)。
-
@Dave:我不明白 dynamic_cast 的意思。 Boost.Any 中没有中间类型。
标签: c++ c++11 type-erasure