BCB中的RTTI机制
BCB中的RTTI機制
RTTI在BCB中其實有兩個意義。首先,針對一般標準的C++中所定義的,RTTI是所謂的Run-Time Type Identification的縮寫。傳統的程序語言中,所謂的數據型態僅在Compile-Time有所作用。舉例而言,您宣告了一個變量a,并且指定其型態為整數。您如何在Run-Time期間知道他的型態是整數呢?很遺憾的是,在原來的C/C++中您是無法知道這樣的事情的。或者會問,這樣的信息有何作用?若是您考慮對象的繼承關系,您就會發現其重要性了。
舉例而言,若您有下面的程序:
class CShape {
??? …
??? public:
??????? virtual void ShowMe() = 0; // Virtual function
} ;
class CRectangle {
??? public:
??????? void ShowMe();
};
viod Show(CShape *someShape) {
??? someShape->ShowMe();
}
int main(void) {
??? CRectangle myRect ;
??? Show(&myRect);
??? CNotShape notShape ;
??? Show(¬Shape); // Error!!
}
?
??? 上面的程序中CShape為base class。而CRectangle繼承它。因此,在main function中的第一個Show()可以正常動作,因為在Show()中,someShape->ShowMe()可以正確的找到在 CRectangle的ShowMe()函式??墒堑诙€Show()就會有問題,原因在于CNotShape并非繼承于CShape,所以沒有 ShowMe()的函式可用。因此,會造成Access Violation的狀況發生。或者會覺得這種狀況不會發生在您身上,但是請想想如果您是鏈接庫的設計者,您如何可確保使用者不會隨便指定奇怪的對象給您呢?所以如果能夠在執行期判斷傳進的對象真正的型態以及其繼承關系,就可以直接判斷傳入的對象可否使用。否則便傳回錯誤。這樣便可避免Access Violation的問題。能夠提供這個解決方法的便是所謂的C++的RTTI機制了。
不過,C++ RTTI機制的功能十分有限。例如,想要進一步的列舉出class所擁有的成員及函式,在Run-Time是無法做到的。因為C++ RTTI僅是一個Identification機制,用來識別型態及其繼承關系。并不包含其完整型態信息。這時,您需要引進VCL所獨有的RTTI機制。在VCL中的RTTI指的是Run-Time Type Information機制。由于是由VCL所提供的RTTI機制,所以僅適用于繼承在TObject之上的類別或對象,其它類別或對象并不適用。
由VCL所提供的RTTI機制,可以讓您清楚的數據類別的信息,對象的信息,以及列舉出所包含的成員及函式。不過,在好用的背后是要付出代價的。對象的信息需要地方來儲存,這會造成而額外的內存以及檢查這些信息的CPU時間的浪費。不過就今日CPU及內存的價格,與RTTI所帶來的方便性相較之下,這些額外的浪費就顯得微不足道了。而Borland在這方面也下了不少奶牷A關于這方面的程序代碼大部分皆以匯編語言寫成,所以處理速度很快。
以下將針對這兩種RTTI分別做說明。
?
?
C++中的RTTI機制
如果您翻閱C++ Builder所附的On-Line Help,您可找到下面這段對于RTTI的說明:
Runtime type identification (RTTI) lets you write portable code that can determine the actual type of a data object at runtime even when the code has access only to a pointer or reference to that object. This makes it possible, for example, to convert a pointer to a virtual base class into a pointer to the derived type of the actual object. Use the dynamic_cast operator to make runtime casts.
The RTTI mechanism also lets you check whether an object is of some particular type and whether two objects are of the same type. You can do this with typeid operator, which determines the actual type of its argument and returns a reference to an object of type const type_info, which describes that type.
You can also use a type name as the argument to typeid, and typeid will return a reference to a const type_info object for that type. The class type_info provides an operator== and an operator!= that you can use to determine whether two objects are of the same type. Class type_info also provides a member function name that returns a pointer to a character string that holds the name of the type.
正如上面所說的,您可透過typeid()運算子來取得type_info的信息。此處應當注意的是typeid()是一個運算子。他與sizeof() 是相同等級的運算子。不過,若要使用typeid()您需要include typeinfo這個項目。您的include寫法如下:
?
#include <typeinfo>
using namespace std;
?
透過typeid()我們可以取得特定的型態的信息。例如,想要比較兩個變量是否為相同型態。您可以寫成下面的形式:
?
template <class T, class D>
bool isSameType(T var1, D var2)
{
??? return (typeid(var1) == typeid(var2));
}
?
這個函式可用來比較兩個變量的型態是否相等。
若您想取得型態的名稱。您可使用typeid()所傳回來的型態的name()函式。例如:
?
int a;
ShowMessage(typeid(int).name());
ShowMessage(typeid(a).name());
?
??? 若您想確認兩者之間有無繼承關系,可使用typeid()所傳回來的型態中的before()函式。before()函式中有一個參數也是一個由 typeid()所傳回的型態信息。以前面的例子來說,若您想切確知道CShape是否在CRectangle之前(也就是是否CRectangle為 CShape的祖先),可用下面的程序來判斷:
?
if( typeid(CShape).before(typeid(CRectangle)) )
{
??? return true ;
}
?
??? 因此,當您想要對一個class進行up casting或是down casting時,可先用這種方式判斷一下,兩者是否有繼承關系,然后才進行轉換。當然,這樣的檢查常常會用到,所以你可能打算把他寫成一個工具函式來用。不過,先等一下!標準的C++已經幫您準備好了!而且不只一個,C++準備了四個casting的工具函式,每一個都有不同的用法及意義。他們分別是:
const_cast<Type>(var)
const_cast是一個compile time的cast。其主要作用為移除或加上型態的 const 限制。舉例來說,您有一個const的整數a。您想要用一個整數指標指向它。
?
??? const i = 0;
??? int *p = &i ; // Compile error! Cannot cast from const to violate.
?
但是您可能非常確定自己想要做什么,所以您可使用const_cast明確的告訴compiler做您要求的動作。
?
??? const i = 0;
??? int *p = const_cast<int *>(&i) ; // OK.
?
同樣的,要把不具const性質的型態轉成const性質也是相同的方法。不過,請務必要知道自己為何這樣做,否則可能會惹上麻煩。
dynamic_cast<Type>(ptr)
在使用dynamic_cast時,Type必需為指定為一個class的指標,否則就必需是void *。若為void *,則ptr所給定的指標將會被轉換為void *,并且任何型態的指針內。然而,真正常用的是用來進行class的up casting或down casting。以前面的CShape及CRectangle而言,您可使用下面的方式進行轉換:
?
??? CShape *sp = dynamic_cast<CShape *>( some_pointer );
??? CRectangle *rp = dynamic_cast<CRectangle *>(some_pointer);
?
或許,上面的范例看起來跟一般的static casting沒有什么差別。其實,差別十分大,我們知道static casting的意思有點類似于強制要求compile幫您進行轉換,所以不會顧形態與形態之間本身是否有繼承關系、是否真的可以轉換。所以稍不注意就常常會有Access Violation的狀況。但是dynamic_cast就不一樣了,他會幫您檢查并且確定來源的型態與目的型態是可進行轉換的。若不能轉換就會傳回 NULL。所以您可以依據dynamic_cast的傳回值來判斷是否轉換成功。
reinterpret_cast<Type>(var)
其中Type必需為pointer, reference, arithmetic type, pointer to function或是pointer to member。reinterpret_cast可以幫您將整數轉變為一個指向某種型態的指針。主要用于當地址必處理放置于整數變量中。要將他轉回原來型態的指針時所使用。
static_cast<Type>(var)
就是我們一般以前常用的static casting的形式。只是為了與前面所介紹的三種casting匹配,而改成了這種形式。所以若您以前常用如下的方式進行casting,不妨換種方式:
?
??? int a ;
??? float b = 10.01
??? a = static_cast<int>(b);
?
不確定轉換的指標會不會與轉換后指針的型態兼容時,請多多使用dynamic_cast。這樣可以避免預想不到的狀況發生。
?
?
VCL的RTTI機制
?
VCL所提供的RTTI機制,可以提供非常詳盡的信息。其大部分都供Borland C++ Builder或Delphi的Design環境使用。這也就是為何在Object Inspector可以看到對象的屬性(Property)及設定其Event了。只要您掌握了VCL上RTTI的精髓,您也可以寫出Object Inspector一樣的功能。
所謂的RTTI可視為用來記錄型態信息的一個Structure。這個部分是由VCL所提供。因此,要使用這些RTTI機制,大部分的狀況下必需作用于繼承自TObject的VCL組件。
我們要如何取得這個記載著型態信息的Structure呢?有幾種方式:
?
方法一
要取得一個VCL組件類別的信息可透過其ClassInfo()這個method。如果您看過VCL的對象階層圖,您就知道ClassInfo()這個 method是在TObject內定義的。所以,所有的VCL組件都可以使用他。仔細看一下Borland所附的On-Line Help;
Returns a pointer to the runtime type information (RTTI) table for the object type.
?
typedef TMetaClass* TClass;
static void * __fastcall ClassInfo(TClass cls);
void * __fastcall ClassInfo(){return ClassInfo(ClassType()); }
?
Description
Use ClassInfo to access the RTTI table that contains information about the object type, its ancestor type, and all of its published properties.
Call ClassInfo with no arguments to obtain the RTTI table for a specific object instance. Call the static TObject::ClassInfo method, passing the metaclass information, to obtain the RTTI table for a class of object when you don’t have an instance.
RTTI is used internally by the development environment. ClassInfo is rarely called directly in an application. TObject includes other methods that provide easier access to RTTI.
?
ClassInfo其實有兩個,一種是TObject::ClassInfo()。另外一個是獨立的static function。其中,第一種適用于已經有確定的instance。而在沒有instance的狀況下,就應當使用static function的方式?;蛘咭獑柸绾蔚玫綄硞€class的TClass信息呢?您需要搭配VCL所提供的__classid這個關鍵詞。他可以取得特定class的TClass信息。例如:要取得TButton的RTTI信息,您需要使用下面的方式:
?
ClassInfo(__classid(TButton));
?
我們也看到ClassInfo()的傳回值是一個void *,這就是指向記載著RTTI信息結構的指針。
除了ClassInfo(),其實還有另外一個方式,就是使用__typeinfo()這個宏。這個宏與ClassInfo()的作用相同。唯一的差別在于ClassInfo()傳回的是一個void *,而__typeinfo()會經過一次的casting動作轉成PTypeInfo的型態,也就是TTypeInfo *的型態。
?
方法二
很不幸的一點,前述的方式僅針對VCL的類別有作用。如果不是VCL類別就會有問題了。例如,某些類別看來很像VCL類別,實際上僅是一個列舉型態。就像是TAlign這個用來指定組件放置行為的型態。雖然也是T開頭。實際上不過就是個列舉型態罷了。所以,前面的方式都會讓您得到 compile error。在Delphi中,有一個名為TypeInfo的函式可以取得各種型態的TTypeInfo數據。但是,他主要的運作是在compile time。這也就是說,你必需在compile time就指定好型態。所以,在BCB中的實用性不大。如果真的有必要。可以另外寫一個Delphi的程序文件,專門利用TypeInfo函式取得 TTypeInfo的數據。關于這個部分,建議您參考后面所提的『Run-Time Type Information(RTTI) In C++ Builder 5』一文。
?
方法三
如果您要存取的是非VCL類別的型態,您可能要參考上面第二點的作法。不過,如果您要存取的是屬于某個VCL類別的__published節中的非 VCL類別型態。那么恭喜您!您未必需要搭配Delphi了。例如:您要取得TAlign這個型態的信息。所幸,在TPanel這個VCL組件中的 Align屬性就是TAlign的型態。而且Align是__published的。因為VCL對于__published內的東西一律會產生其RTTI 詳細信息。所以,我們就可以透過這種方式來存取TAlign的RTTI信息了。用法如下:
?
#include <typinfo .hpp> // Note: it is “typinfo”, not “typeinfo”
…
??? PPropInfo pp = GetPropInfo(__typeinfo(TPanel), "Align") ;
??? PTypeInfo pt = ((pp==NULL)? NULL : *(pp->PropType));
?
?
VCL RTTI有何信息?
C++本身的RTTI用途蠻容易了解的,但是VCL的RTTI呢?取得他的TTypeInfo 信息后有何作用呢?
其實,秘密都藏在$(BCB)\Source\VCL\typinfo.pas中。在這個檔案中存放了許多與VCL RTTI相關的信息及程序代碼。如果您對于Delphi或是Object Pascal不熟悉,沒關系,看看$(BCB)\Include\VCL\typinfo.hpp。這個是由BCB所自動產生出來的include檔案。雖然沒有程序代碼在內。但是,光看里面的定義,也大概可以猜出其作用為何。在此,我們將針對這個檔案內所提供的數據結構及相關函式進行說明。
首先,我們來看看前面一直提到的TTypeInfo這個structure。您可在typinfo.hpp中找到他的定義。
?
struct TTypeInfo
{
??? TTypeKind Kind;
??? System::ShortString Name;
} ;
?
這個結構非常簡單,只有兩個項目,其中TTypeKind是一個列舉型態。Kind記錄這是何種的型態。而Name則記載了該型態的名字。在VCL中針對TTypeKind的列舉型態,共有下面這些項目:
列舉值 說明?
tkUnknown 保留,未使用的值。?
tkInteger 整數?
tkChar Char或是AnsiChar的型態?
tkEnumeration 列舉型態,包含Boolean, ByteBool, WordBool, LongBool及Bool?
tkFloat 浮點數?
tkString ShortString 型態?
tkSet Set 型態?
tkClass ? 類別型態?
tkMethod Procedure或是function型態?
tkWChar ?? WideChar 型態?
tkLString ???? WideString型態?
tkVariant ? Variant型態?
tkArray ?? Array型態?
tkRecord ?? Record型態(即struct)?
tkInterface ?? Interface型態?
tkInt64 ? Int64型態?
tkDynArray ? ?動態數組型態(即DynamicArray)?
??? 或許您會覺得奇怪,怎么好像一堆沒看過的型態。其實,這些對應的值都是Delphi中的型態。所以,您需要測試一下看看在BCB中,哪些型態會對應到上面的項目。
有了上面這個信息,您就可以取得在VCL的型態信息,并且藉此來判斷所取得的型態為何。當然未必所有的型態都可用Kind來加以判斷,此時建議您搭配Name一起來加以判斷,相信就可清楚的判斷出您要的型態了。
實際上,光是TTypeInfo的內容是不夠用的,因為他是所有型態共同的部分,針對其它屬于型態相關的信息,在TTypeInfo中是看不到的。若需要取得這些與個別型態相關的信息,就需要用到在TypInfo.hpp后面所記載的一些工具函式。首先,最重要的工具函式就是:
?
PTypeData __fastcall GetTypeData(PTypeInfo TypeInfo);
?
這個函式的參數為一個指向TTypeInfo的指標,透過這個TTypeInfo的信息,會傳回另一個指向TTypeData的指標。這就是我們所要的個別型態的詳細數據。不幸的是,如果您去查鋁ypInfo.hpp中的訊息,您會發現到TTypeData其實是一堆struct的聯集。主要是因為不同的型態所需記錄的東西不同所致。
前面我們曾經提到透過BCB我們可以取得放在__published部分的屬性數據。那么,我們可以取得所有屬性的列表嗎?答案是可以的,只要他是放在__published中。要取得這個信息,您需要透過一些在TypInfo.hpp中所定義的函式的幫助。主要有幾個函式能夠幫助我們取得屬性的信息他們分別是:
?
extern PACKAGE PPropInfo __fastcall GetPropInfo(System::TObject*
???????? Instance, const AnsiString PropName, TTypeKinds AKinds =
???????? System::Set<TTypeKind, tkUnknown, tkDynArray> () );
extern PACKAGE PPropInfo __fastcall GetPropInfo(TMetaClass* AClass,
???????? const AnsiString PropName, TTypeKinds AKinds =
???????? System::Set<TTypeKind, tkUnknown, tkDynArray> () );
extern PACKAGE PPropInfo __fastcall GetPropInfo(PTypeInfo TypeInfo, const AnsiString PropName);
extern PACKAGE PPropInfo __fastcall GetPropInfo(PTypeInfo TypeInfo, const AnsiString PropName, TTypeKinds AKinds);
extern PACKAGE void __fastcall GetPropInfos(PTypeInfo TypeInfo, PPropList PropList);
extern PACKAGE int __fastcall GetPropList(PTypeInfo TypeInfo, TTypeKinds TypeKinds, PPropList PropList, bool SortList = true);
extern PACKAGE int __fastcall GetPropList(PTypeInfo TypeInfo, /* out */ PPropList &PropList);
extern PACKAGE int __fastcall GetPropList(System::TObject* AObject, /* out */ PPropList &PropList);
?
??? 簡單的說,如果你已經很切確的知道自己所要找的是某個屬性,就請用GetPropInfo。如果您希望取得所有的屬性,可以使用GetPropInfos函式。如果您希望只取得屬于某種型態的屬性,或是對所取得的屬性進行排序,建議使用GetPropList函式。
舉例來說,如果您要取得Form1中的Align屬性的型態信息。您可使用如下的程序代碼:
?
PPropInfo pi ;
pi = GetPropInfo(Form1->ClassInfo(), "Align");
?
若您希望取得某個VCL組件的所有屬性,可使用
?
TPropList List;
GetPropInfos(Form1->ClassInfo(),(PPropList)&List);
?
如果您想取得符合某些特定型態的屬性,可用:
?
TPropList List;
int Count = GetPropList((PTypeInfo)(Form1->ClassInfo()), tkAny, (PPropList)&List);
?
不過這里有個問題,如果您去看一下TPropList的定義,會發現他其實是一個非常大的指針數組。這樣內存是蠻浪費的,所以建議您可以換種方式:
?
int count = GetPropList((PTypeInfo)(Form1->ClassInfo()), tkAny, NULL);
PPropList list = new PPropInfo[count];
try {
??? GetPropList((PTypeInfo)ClassInfo(), tkAny, list);
}
__finally {
??? delete [ ] list ;
}
?
其中,TTypeKinds是用來記錄您期望符合的型態。他是一個Set的型態。舉例來說,如果您要取得整數,浮點數這兩種型態。在TTypeKinds的部分可用下面的形式:
?
TTypeKinds() << tkInteger << tkFloat ;
?
如果您是BCB 5的使用者,這里請您要注意了,BCB 5在這個地方似乎有點問題,也就是說他的typinfo.hpp在這個地方的定義是錯的。正確的定義應該是下面這樣的:
?
#define tkAny (System::Set<TTypeKind, tkUnknown, tkDynArray> ()\
???????? << TTypeKind(0) << TTypeKind(1) << TTypeKind(2)\
???????? << TTypeKind(3) << TTypeKind(4) << TTypeKind(5)\
???????? << TTypeKind(6) << TTypeKind(7) << TTypeKind(8)\
???????? << TTypeKind(9) << TTypeKind(10) << TTypeKind(11)\
???????? << TTypeKind(12) << TTypeKind(13) << TTypeKind(14)\
???????? << TTypeKind(15) << TTypeKind(16) << TTypeKind(17) )
#define tkMethods (System::Set<TTypeKind, tkUnknown, tkDynArray> () << TTypeKind(8) )
#define tkProperties (System::Set<TTypeKind, tkUnknown,\
???????? tkDynArray> () << TTypeKind(1) << TTypeKind(2) << \
???????? TTypeKind(3) << TTypeKind(4) << TTypeKind(5) << \
???????? TTypeKind(6) << TTypeKind(7) << TTypeKind(9) << \
???????? TTypeKind(10) << TTypeKind(11) << TTypeKind(12) << \
???????? TTypeKind(13) << TTypeKind(14) << TTypeKind(15) << \
???????? TTypeKind(16) << TTypeKind(17) )
?
??? 奇怪的是,在BCB 4之前與BCB 6都是正確的,僅在BCB 5是錯的。建議您手動將typinfo.hpp更正過來。
當取得我們所要的屬性后,接下來的動作就是要存取其屬性值。舉例來說,如果要設定某個bool型態的屬性為true,或者是取得其現在的屬性,該如何做呢?本來這是十分復雜的步驟,不過因為typinfo.hpp中提供了不少好用的函式,所以我們可以很輕易的存取這些屬性值了。這些方便的函式及其定義與說明如下:
?
?
判斷是否為__published的屬性:
extern PACKAGE bool __fastcall IsPublishedProp(System::TObject* Instance, const AnsiString PropName);
extern PACKAGE bool __fastcall IsPublishedProp(TMetaClass* AClass, const AnsiString PropName);
extern PACKAGE bool __fastcall IsStoredProp(System::TObject* Instance, const AnsiString PropName);
extern PACKAGE bool __fastcall IsStoredProp(System::TObject* Instance, PPropInfo PropInfo);
?
?
取得與比較屬性的型態:
extern PACKAGE bool __fastcall PropIsType(System::TObject* Instance, const AnsiString PropName, TTypeKind TypeKind);
extern PACKAGE bool __fastcall PropIsType(TMetaClass* AClass, const AnsiString PropName, TTypeKind TypeKind);
extern PACKAGE TTypeKind __fastcall PropType(System::TObject* Instance, const AnsiString PropName);
extern PACKAGE TTypeKind __fastcall PropType(TMetaClass* AClass, const AnsiString PropName);
?
?
存取屬性(不管型態):
extern PACKAGE Variant __fastcall GetPropValue(System::TObject* Instance, const AnsiString PropName, bool PreferStrings = true);
extern PACKAGE void __fastcall SetPropValue(System::TObject* Instance, const AnsiString PropName, const Variant &Value);
?
?
存取整數型態屬性:
extern PACKAGE int __fastcall GetOrdProp(System::TObject* Instance, const AnsiString PropName);
extern PACKAGE void __fastcall SetOrdProp(System::TObject* Instance, const AnsiString PropName, int Value);
extern PACKAGE int __fastcall GetOrdProp(System::TObject* Instance, PPropInfo PropInfo);
extern PACKAGE void __fastcall SetOrdProp(System::TObject* Instance, PPropInfo PropInfo, int Value);
?
?
存取浮點數型態屬性:
extern PACKAGE Extended __fastcall GetFloatProp(System::TObject* Instance, const AnsiString PropName);
extern PACKAGE void __fastcall SetFloatProp(System::TObject* Instance, const AnsiString PropName, const Extended Value);
extern PACKAGE Extended __fastcall GetFloatProp(System::TObject* Instance, PPropInfo PropInfo);
extern PACKAGE void __fastcall SetFloatProp(System::TObject* Instance, PPropInfo PropInfo, const Extended Value);
?
?
存取列舉型態屬性:
extern PACKAGE AnsiString __fastcall GetEnumProp(System::TObject* Instance, const AnsiString PropName);
extern PACKAGE void __fastcall SetEnumProp(System::TObject* Instance, const AnsiString PropName, const AnsiString Value);
extern PACKAGE AnsiString __fastcall GetEnumProp(System::TObject* Instance, PPropInfo PropInfo);
extern PACKAGE void __fastcall SetEnumProp(System::TObject* Instance, PPropInfo PropInfo, const AnsiString Value);
extern PACKAGE AnsiString __fastcall GetEnumName(PTypeInfo TypeInfo, int Value);
?
?
存取集合型態屬性:
extern PACKAGE AnsiString __fastcall GetSetProp(System::TObject* Instance, const AnsiString PropName, bool Brackets = false);
extern PACKAGE void __fastcall SetSetProp(System::TObject* Instance, const AnsiString PropName, const AnsiString Value);
extern PACKAGE AnsiString __fastcall GetSetProp(System::TObject* Instance, PPropInfo PropInfo, bool Brackets = false);
extern PACKAGE void __fastcall SetSetProp(System::TObject* Instance, PPropInfo PropInfo, const AnsiString Value);
extern PACKAGE AnsiString __fastcall SetToString(PPropInfo PropInfo, int Value, bool Brackets = false);
extern PACKAGE int __fastcall StringToSet(PPropInfo PropInfo, const AnsiString Value);
?
?
存取對象型態屬性:
extern PACKAGE System::TObject* __fastcall GetObjectProp(System::TObject* Instance, const AnsiString PropName, TMetaClass* MinClass = 0x0);
extern PACKAGE void __fastcall SetObjectProp(System::TObject* Instance, const AnsiString PropName, System::TObject* Value);
extern PACKAGE TMetaClass* __fastcall GetObjectPropClass(System::TObject* Instance, const AnsiString PropName);
extern PACKAGE System::TObject* __fastcall GetObjectProp(System::TObject* Instance, PPropInfo PropInfo, TMetaClass* MinClass = 0x0);
extern PACKAGE void __fastcall SetObjectProp(System::TObject* Instance, PPropInfo PropInfo, System::TObject* Value, bool ValidateClass = true);
extern PACKAGE TMetaClass* __fastcall GetObjectPropClass(System::TObject* Instance, PPropInfo PropInfo);
extern PACKAGE TMetaClass* __fastcall GetObjectPropClass(PPropInfo PropInfo);
?
?
存取AnsiString型態屬性:
extern PACKAGE AnsiString __fastcall GetStrProp(System::TObject* Instance, const AnsiString PropName);
extern PACKAGE void __fastcall SetStrProp(System::TObject* Instance, const AnsiString PropName, const AnsiString Value);
extern PACKAGE AnsiString __fastcall GetStrProp(System::TObject* Instance, PPropInfo PropInfo);
extern PACKAGE void __fastcall SetStrProp(System::TObject* Instance, PPropInfo PropInfo, const AnsiString Value);
?
?
存取WideString型態屬性:
extern PACKAGE WideString __fastcall GetWideStrProp(System::TObject* Instance, const AnsiString PropName);
extern PACKAGE void __fastcall SetWideStrProp(System::TObject* Instance, const AnsiString PropName, const WideString Value);
extern PACKAGE WideString __fastcall GetWideStrProp(System::TObject* Instance, PPropInfo PropInfo);
extern PACKAGE void __fastcall SetWideStrProp(System::TObject* Instance, PPropInfo PropInfo, const WideString Value);
?
?
存取Variant型態屬性:
extern PACKAGE Variant __fastcall GetVariantProp(System::TObject* Instance, const AnsiString PropName);
extern PACKAGE void __fastcall SetVariantProp(System::TObject* Instance, const AnsiString PropName, const Variant &Value);
extern PACKAGE Variant __fastcall GetVariantProp(System::TObject* Instance, PPropInfo PropInfo);
extern PACKAGE void __fastcall SetVariantProp(System::TObject* Instance, PPropInfo PropInfo, const Variant &Value);
?
?
存取Method型態屬性:
extern PACKAGE System::TMethod __fastcall GetMethodProp(System::TObject* Instance, const AnsiString PropName);
extern PACKAGE void __fastcall SetMethodProp(System::TObject* Instance, const AnsiString PropName, const System::TMethod &Value);
extern PACKAGE System::TMethod __fastcall GetMethodProp(System::TObject* Instance, PPropInfo PropInfo);
extern PACKAGE void __fastcall SetMethodProp(System::TObject* Instance, PPropInfo PropInfo, const System::TMethod &Value);
?
?
存取Int64型態屬性:
extern PACKAGE __int64 __fastcall GetInt64Prop(System::TObject* Instance, const AnsiString PropName);
extern PACKAGE void __fastcall SetInt64Prop(System::TObject* Instance, const AnsiString PropName, const __int64 Value);
extern PACKAGE __int64 __fastcall GetInt64Prop(System::TObject* Instance, PPropInfo PropInfo);
extern PACKAGE void __fastcall SetInt64Prop(System::TObject* Instance, PPropInfo PropInfo, const __int64 Value);
?
?
存取Interface型態屬性:
extern PACKAGE System::_di_IInterface __fastcall GetInterfaceProp(System::TObject* Instance, const AnsiString PropName);
extern PACKAGE void __fastcall SetInterfaceProp(System::TObject* Instance, const AnsiString PropName, const System::_di_IInterface Value);
extern PACKAGE System::_di_IInterface __fastcall GetInterfaceProp(System::TObject* Instance, PPropInfo PropInfo);
extern PACKAGE void __fastcall SetInterfaceProp(System::TObject* Instance, PPropInfo PropInfo, const System::_di_IInterface Value);
?
?
??? 理論上,只要有 SetPropValue 與 GetPropValue 這兩組函式就夠了??墒?#xff0c;除非您很熟悉 TTypeData 的細節,否則建議您還是使用上述的這些與個別型態相關的函式吧。況且,Borland并未把上面的技術正式公布出來,其中的一個理由就是這些內部結構還有可能會修改。所以,還是別自己亂動的好。另外一件事情就是,上面的函式未必所有C++ Builder的版本都有。建議您還是先看看自己的typinfo.hpp再說吧。
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/aniven/archive/2006/05/24/753200.aspx
轉載于:https://www.cnblogs.com/zhangdongsheng/archive/2011/04/10/2011008.html
總結
以上是生活随笔為你收集整理的BCB中的RTTI机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: javascript正则表达式(一)
- 下一篇: ASP.NET开源MVC框架Vici M