突发奇想,想根据类的名字(一个C++的string),创建相应的类实例,除了这个string,不用其他的东西。
比方说我已经声明了一个PClassStr这个类,现在我用字符串"PClassStr"来创建一个PClassStr这个类的实例。google了一下,得到的大多数是有关typeof和typeid相关,进一步就是C++0x,还有个auto。
typeid是萃取出某个C++类(或对象)的信息,得到一个typeinfo instance,然后就可以根据typeinfo判断一个类对象是否是某个class的对象,或者是两个类对象是否同一个class的对象。
typeinfo类重定义了==、 != 就是完成了上述的功能,自然也定义了能获取本类的相关信息的函数。在这里派不上用场。
typeof关键字貌似只能是GNU C编译器支持,具体没考证。
具体就是:
int *a;
typeof(*a) b; //当然b就是int类型了
但是并不能满足我的需求,我只需要根据一个string,就能创建一个对象,就像java中那样,如果用typeof,那么似乎我必须得有我想创建的那个类的某个实例,正如上面我必须有个跟int类型相关的对象a,也就是我想创建PClassStr这个类的实例,那么我得有PClassStr的某个对象,typeof的功能确实很重要,但是这里使不上力。
模板类的内嵌类型
template <typename T>
class PClassStr
{
public:
typedef T value_type;
//....
}
大体如此,正如vector里面的 vector<PClassStr>::value_type,跟上面的typeof一样的,始终跳不出在代码中要先写上某个类的类型,然后再写上变量名这个圈套(如 Type variable)。
其实解决的办法微软早就解决了,在设计MFC的时候,微软就把它搞出来了。侯捷的<<深入浅出MFC>>中已对此深入剖析了一番,这里我简述一下,并且从MFC的源码中抽取出相关的宏实现个小程序,效果还可以~
我们知道MFC中有个类的层次,CObject是顶层类,其他的类都是继承该类,形成一个类的体系,其实java也是采用这种类体系结构。
我们要在每个定义的类里面都内嵌一个static结构体(CRuntimeClass),里面记录这个类的名字,创建本类对象的函数指针(CreateObject),等等,主要是这两个字段。在创建每个类的时候我们会把这个类的CRuntimeClass加入到一个全局链表中。
这样给定一个类的名字(一个string),只需要遍历这个全局的链表,找到对应这个string的CRuntimeClass(当然类名是不会重复的),因为这个CRuntimeClass里面存在一个函数指针,专门用来创建对应类的对象的,如此就实现了我的要求。
在我的小程序中,所有类都继承自PObject
每个类的声明中都应该包含如下相似代码,你可以写成宏定义:
public:
static struct CRuntimeClass classPClassStr;
static struct AFX_CLASSINIT _init_PClassStr;
virtual struct CRuntimeClass* GetRuntimeClass() const;
static PObject* CreateObject();
在类的实现中需要包含如下相似代码:
struct CRuntimeClass PClassStr::classPClassStr = {
"PClassStr",
sizeof(PClassStr),
0XFFFF,
PClassStr::CreateObject,
(&PObject::classPObject),
NULL, &PClassStr::_init_PClassStr };
struct AFX_CLASSINIT PClassStr::_init_PClassStr(&(PClassStr::classPClassStr));
struct CRuntimeClass* PClassStr::GetRuntimeClass() const
{
return (&PClassStr::classPClassStr);
}
PObject* PClassStr::CreateObject()
{
return new PClassStr;
}
这里要注意AFX_CLASSINIT结构体的妙用,还有全局链表如何管理。
有关解释具体参见<<深入浅出MFC>>,想看相关宏定义查看MFC框架的源代码,有关全局链表头参见小程序代码。
程序中没有对类的继承体系结构进行管理,只是简单地将所有类加入到单链表中,它只是实现了我的想法,要想实现typeof的功能还有很多要做。
--EOF