支援多基類的C 類反射實現

2022-04-04 09:57:28 字數 4470 閱讀 7119

本文中的類反射指的是例項的型別識別(rtti)、動態建立,繼承鏈遍歷能力,不討論成員函式、成員變數等的反射。即實現以下類似介面:

class

foo :

public

object

;object

*obj1

=new

foo();

iskindof(obj1,

"foo

");

//型別識別

object

*obj2

=createobject(

"foo

");

//動態建立

getbaseclass(obj1) =="

object

"

本小節實現類反射的三大能力:例項型別識別動態建立繼承鏈遍歷。為了類繼承結構的組織方便,實現了類反射的類通常會有乙個公共基類,例如在mfc中就是cobject。我們定義乙個公共基類:

class

object

};

首先實現例項型別識別例項型別識別可以考慮使用typeid(instance).name()來實現,但是需要該類具有虛函式表,並且返回值也是編譯器相關的,而不是真正的類名。我們在每個類中新增乙個靜態成員變數來儲存類資訊,並定義乙個虛函式時每個例項可以正確獲取到類資訊。為了實現方便,這裡定義乙個classinfo類來表示類資訊:

class

classinfo

const

std::

string

&getclassname()

const

bool

iskindof(

const

std::

string

&classname)

const

private

: std::

string

m_classname;

};

在每個類中新增乙個靜態成員變數和虛函式:

//

.hclass

foo :

public

object

static

classinfo ms_classinfo;

};//

.cpp

classinfo foo::ms_classinfo(

"foo");

這樣我們就簡單地實現了例項型別識別,可以做如下測試:

object 

*obj

=new

foo();

assert(obj

->

getclasinfo()

->

iskindof(

"foo

"));

然後實現動態建立能力,先定義介面,新增了成員函式findclass(靜態)和createobject:

classinfo

*fooinfo

=classinfo::findclass(

"foo");

assert(fooinfo);

object

*obj

=fooinfo

->

createobject();

定義乙個hash單例,儲存類名到classinfo的對映,findclass使用該hash表查詢。classinfo並不知道如何建立例項,需要我們在每個類中新增createobject,然後傳遞給classinfo。

+

typedef object*(

*objectconstructor)(

void);

class

classinfo

const

std::

string

&getclassname()

const

bool

iskindof(

const

std::

string

&classname)

const

+object

*createobject()

const+

+static

classinfo

*findclass(

const

std::

string

&classname)+

private:+

void

register()+

std::

string

m_classname;

+objectconstructor m_objectctor;

}; //.h

class

foo :

public

object +

static

object

*createobject()+

static

classinfo ms_classinfo;

};//

.cpp

classinfo foo::ms_classinfo(

"foo

", (objectconstructor)(foo::createobject));

最後,在classinfo中加入繼承鏈遍歷(為了簡化問題,只考慮單繼承):

class

classinfo +

const

classinfo

*getbaseclass()

const+

private: +

const

classinfo

*m_baseinfo;

...}; //

.cpp

classinfo foo::ms_classinfo(

"foo",

(objectconstructor)(foo::createobject),+&

object::ms_classinfo);

現在我們已經實現了所有的功能,也可以繼續給classinfo新增一些有用的介面,例如iskindof等。但是,實際使用時每個類都要手動寫這麼多**是很麻煩的,使用巨集可以幫我們簡化:

typedef object*(

*objectconstructor)(

void

);#define

declare_class(name) \

public

: \

static

classinfo ms_classinfo; \

virtual

classinfo

*getclassinfo()

const

; \

static

object

*createobject()

#define

implement_class(name, basename) \

classinfo name::ms_classinfo(#name, \

(objectconstructor)(name::createobject), \

&basename::ms_classinfo) \

classinfo

*name::getclassinfo()

const

\ \

object

*name::createobject() \

//.h

class

foo :

public

object;//

.cpp

implement_class(foo, object)

本文只是為了闡述思路,實際使用時還需要根據類的特徵來定製不同的巨集(是否支援動態建立,多基類支援等)。

上文中實現的類反射需要所有的類擁有乙個共同基類,但是有時候乙個工程中可能需要使用多套類繼承體系,這時又需要重寫一套反射類和巨集。我們可以使用模板定製乙個更靈活的類反射系統。類資訊classinfo需要加乙個模板引數作為該組的共同基類:

template 

<

class

_groupbase

>

class

classinfo

;

具體實現不再贅述,附上**:

link

C 多繼承與虛基類

多繼承的定義 派生類的基類大於乙個 語法 class 派生類名 繼承方式1 基類名1,繼承方式2 基類名2.多重繼承與建構函式的關係 多重繼承時建構函式的作用 1 初始化派生類 自己 2 呼叫該派生類所有基類建構函式,並且為所有基類傳參 引數個數必須包含所有基類所需引數 建構函式語法 派生類建構函式...

C 虛基類的實現機制

在 深度探索c 物件模型 裡,有乙個問題,也是去公司面試的時候那些技術人員常問的問題 在c 中,obj是乙個類的物件,p是指向obj的指標,該類裡面有個資料成員mem,請問obj.mem和p mem在實現和效率上有什麼不同。答案是 只有一種情況下才有重大差異,該情況必須滿足以下3個條件 1 obj ...

C 排序演算法 基類的實現

論壇中經常有人問選擇法 冒泡法排序演算法用c 怎麼實現,正好我手頭上有這方面的 乾脆拿出來跟大家分享一下。其實 已經寫了很久了,只是平時工作比較忙,沒時間整理。現在失業了,每天呆在家裡實在無聊,就抽空把這部分 整理出來。好了,廢話少說,進入正題吧。排序演算法,首先應該考慮的是通用性,不管是陣列,還是...