正如Alf所说,这是不必要的。
typeid
已经提供了一个独特的类标识符,尽管这个标识符不是整数。只是为了好玩,如果我被允许放宽“公共基类”条件,那么:
inline unsigned int counter() {
static unsigned int count = 0;
return ++count;
}
struct BaseClass {
virtual unsigned int GetID() = 0;
virtual ~BaseClass() {}
};
template <typename D>
struct IntermediateClass : BaseClass {
virtual unsigned int GetID() {
static unsigned int thisid = counter();
return thisid;
}
};
struct Derived : IntermediateClass<Derived> {
...
};
如果要在多线程程序中使用counter
,则需要添加线程安全性。
显然,ID仅在程序的给定运行中是唯一的。
如果您的继承层次结构很深,并且有许多具有不同签名的构造函数用于不同的类,则需要在每个派生类和其直接基类之间插入IntermediateClass。但是,您始终可以按如下方式退出所有这些:
inline unsigned int counter() {
static unsigned int count = 0;
return ++count;
}
struct BaseClass {
virtual unsigned int GetID() = 0;
virtual ~BaseClass() {}
};
template <typename D>
unsigned int ThisID(const D *) {
static unsigned int thisid = counter();
return thisid;
}
struct Derived : BaseClass {
virtual unsigned int GetID() { return ThisID(this); }
...
};
我猜这里有一个新语言特性的“机会”:在基类中定义一个虚函数,它是一个带有一个“typename”模板参数的模板函数,并且在每个派生类中自动重写,使用该派生类作为模板参数。由于虚拟模板函数是非法的,因此这是想象中的语法:
struct BaseClass {
template <typename Derived>
virtual unsigned int GetID() {
static unsigned int thisid = counter();
return thisid;
}
virtual ~BaseClass() {}
};
很难仅基于想要重新实现RTTI来证明一种语言特性的合理性,这点需要注意...