第三回 執行時類資訊(Runtime Class Information)
阿新 • • 發佈:2018-12-27
為清晰起見,省略了行末的\ )
#define DECLARE_CLASS(clss)
public:
//類資訊,派生自基類CClass
class CClass_##clss:public CClass
{
public:
virtual void *New() { return _pool.Alloc(); }
virtual void Delete(void *p) { _pool.Free((clss*)p); }
CMemPool<clss> _pool;//這個類的記憶體池
};
static CClass_##clss *_instantiate()
{
static CClass_##clss instance;
instance.SetName(#clss); //設定類的名稱,並註冊到全域性類資訊表格中去
return &instance;
}
CClass *GetClass(){return _class;}
static CClass_##clss *_class; //靜態變數
*.然後再定義一個巨集,用來實現RtCIS:
#define IMPLEMENT_CLASS(clss)
clss::CClass_##clss * clss::_class=clss::_instantiate();//定義並初始化靜態變數
*.再定義幾個巨集用來方便的使用這套系統:
#define Class_New(clss) (clss*)(clss::_class->New())
#define Class_Delete(p) (p)->GetClass()->Delete(p)
#define Class_NewByName(clssname) CClass::NewByName(clssname)
#define Class_GetName(p) (p)->GetClass()->GetName()
*.下面是一個例子,關於水果的:
在標頭檔案裡:
class CFruit
{
public:
virtual CClass*GetClass()=0;
//...
//...
};
class CApple:public CFruit
{
public:
DECLARE_CLASS(CApple);
//...
//...
};
class COrange:public CFruit
{
public:
DECLARE_CLASS(COrange);
//...
//...
};
class CGrape:public CFruit
{
public:
DECLARE_CLASS(CGrape);
//...
//...
};
在cpp檔案裡:
IMPLEMENT_CLASS(CApple);
IMPLEMENT_CLASS(COrange);
IMPLEMENT_CLASS(CGrape);
實際使用:
int main()
{
CFruit* fruit1=Class_New(CApple);
CFruit* fruit2=Class_New(COrange);
CFruit* fruit3=Class_NewByName("CGrape");
assert(std::string("CApple")==Class_GetName(fruit1));
assert(std::string("COrange")==Class_GetName(fruit2));
assert(std::string("CGrape")==Class_GetName(fruit3));
Class_Delete(fruit1);
Class_Delete(fruit2);
Class_Delete(fruit3);
}
另外,這兩天在看havok的物理引擎,它的物件分配也採用了類似的方法,並且有一個比較好的特性就是對於某一個類,可以在每一個執行緒裡為它配備一個獨立的記憶體分配器(這樣就可以避免在記憶體分配程式碼里加鎖,有助於提高效率),比如
void thread1()
{
CFruit* fruit1=Class_New(CApple);
Class_Delete(fruit1);
}
void thread2()
{
CFruit* fruit2=Class_New(CApple);
Class_Delete(fruit2);
}
fruit1和fruit2是自動從兩個獨立的記憶體池裡分配出來的,我還沒看havok是怎麼實現的,不過應該不會太麻煩.希望將來有時間加這個feature.
#define DECLARE_CLASS(clss)
public:
//類資訊,派生自基類CClass
class CClass_##clss:public CClass
{
public:
virtual void *New() { return _pool.Alloc(); }
virtual void Delete(void *p) { _pool.Free((clss*)p); }
CMemPool<clss> _pool;//這個類的記憶體池
};
static CClass_##clss *_instantiate()
{
static CClass_##clss instance;
instance.SetName(#clss); //設定類的名稱,並註冊到全域性類資訊表格中去
return &instance;
}
CClass *GetClass(){return _class;}
static CClass_##clss *_class; //靜態變數
*.然後再定義一個巨集,用來實現RtCIS:
#define IMPLEMENT_CLASS(clss)
clss::CClass_##clss * clss::_class=clss::_instantiate();//定義並初始化靜態變數
*.再定義幾個巨集用來方便的使用這套系統:
#define Class_New(clss) (clss*)(clss::_class->New())
#define Class_Delete(p) (p)->GetClass()->Delete(p)
#define Class_NewByName(clssname) CClass::NewByName(clssname)
#define Class_GetName(p) (p)->GetClass()->GetName()
*.下面是一個例子,關於水果的:
在標頭檔案裡:
class CFruit
{
public:
virtual CClass*GetClass()=0;
//...
//...
};
class CApple:public CFruit
{
public:
DECLARE_CLASS(CApple);
//...
//...
};
class COrange:public CFruit
{
public:
DECLARE_CLASS(COrange);
//...
//...
};
class CGrape:public CFruit
{
public:
DECLARE_CLASS(CGrape);
//...
//...
};
在cpp檔案裡:
IMPLEMENT_CLASS(CApple);
IMPLEMENT_CLASS(COrange);
IMPLEMENT_CLASS(CGrape);
實際使用:
int main()
{
CFruit* fruit1=Class_New(CApple);
CFruit* fruit2=Class_New(COrange);
CFruit* fruit3=Class_NewByName("CGrape");
assert(std::string("CApple")==Class_GetName(fruit1));
assert(std::string("COrange")==Class_GetName(fruit2));
assert(std::string("CGrape")==Class_GetName(fruit3));
Class_Delete(fruit1);
Class_Delete(fruit2);
Class_Delete(fruit3);
}
另外,這兩天在看havok的物理引擎,它的物件分配也採用了類似的方法,並且有一個比較好的特性就是對於某一個類,可以在每一個執行緒裡為它配備一個獨立的記憶體分配器(這樣就可以避免在記憶體分配程式碼里加鎖,有助於提高效率),比如
void thread1()
{
CFruit* fruit1=Class_New(CApple);
Class_Delete(fruit1);
}
void thread2()
{
CFruit* fruit2=Class_New(CApple);
Class_Delete(fruit2);
}
fruit1和fruit2是自動從兩個獨立的記憶體池裡分配出來的,我還沒看havok是怎麼實現的,不過應該不會太麻煩.希望將來有時間加這個feature.