日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BCB中的RTTI机制

發(fā)布時(shí)間:2024/4/14 编程问答 57 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BCB中的RTTI机制 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

BCB中的RTTI機(jī)制
RTTI在BCB中其實(shí)有兩個(gè)意義。首先,針對(duì)一般標(biāo)準(zhǔn)的C++中所定義的,RTTI是所謂的Run-Time Type Identification的縮寫。傳統(tǒng)的程序語言中,所謂的數(shù)據(jù)型態(tài)僅在Compile-Time有所作用。舉例而言,您宣告了一個(gè)變量a,并且指定其型態(tài)為整數(shù)。您如何在Run-Time期間知道他的型態(tài)是整數(shù)呢?很遺憾的是,在原來的C/C++中您是無法知道這樣的事情的。或者會(huì)問,這樣的信息有何作用?若是您考慮對(duì)象的繼承關(guān)系,您就會(huì)發(fā)現(xiàn)其重要性了。
舉例而言,若您有下面的程序:


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(&notShape); // Error!!
}
?
??? 上面的程序中CShape為base class。而CRectangle繼承它。因此,在main function中的第一個(gè)Show()可以正常動(dòng)作,因?yàn)樵赟how()中,someShape->ShowMe()可以正確的找到在 CRectangle的ShowMe()函式。可是第二個(gè)Show()就會(huì)有問題,原因在于CNotShape并非繼承于CShape,所以沒有 ShowMe()的函式可用。因此,會(huì)造成Access Violation的狀況發(fā)生。或者會(huì)覺得這種狀況不會(huì)發(fā)生在您身上,但是請(qǐng)想想如果您是鏈接庫的設(shè)計(jì)者,您如何可確保使用者不會(huì)隨便指定奇怪的對(duì)象給您呢?所以如果能夠在執(zhí)行期判斷傳進(jìn)的對(duì)象真正的型態(tài)以及其繼承關(guān)系,就可以直接判斷傳入的對(duì)象可否使用。否則便傳回錯(cuò)誤。這樣便可避免Access Violation的問題。能夠提供這個(gè)解決方法的便是所謂的C++的RTTI機(jī)制了。
不過,C++ RTTI機(jī)制的功能十分有限。例如,想要進(jìn)一步的列舉出class所擁有的成員及函式,在Run-Time是無法做到的。因?yàn)镃++ RTTI僅是一個(gè)Identification機(jī)制,用來識(shí)別型態(tài)及其繼承關(guān)系。并不包含其完整型態(tài)信息。這時(shí),您需要引進(jìn)VCL所獨(dú)有的RTTI機(jī)制。在VCL中的RTTI指的是Run-Time Type Information機(jī)制。由于是由VCL所提供的RTTI機(jī)制,所以僅適用于繼承在TObject之上的類別或?qū)ο?#xff0c;其它類別或?qū)ο蟛⒉贿m用。
由VCL所提供的RTTI機(jī)制,可以讓您清楚的數(shù)據(jù)類別的信息,對(duì)象的信息,以及列舉出所包含的成員及函式。不過,在好用的背后是要付出代價(jià)的。對(duì)象的信息需要地方來儲(chǔ)存,這會(huì)造成而額外的內(nèi)存以及檢查這些信息的CPU時(shí)間的浪費(fèi)。不過就今日CPU及內(nèi)存的價(jià)格,與RTTI所帶來的方便性相較之下,這些額外的浪費(fèi)就顯得微不足道了。而Borland在這方面也下了不少奶牷A關(guān)于這方面的程序代碼大部分皆以匯編語言寫成,所以處理速度很快。
以下將針對(duì)這兩種RTTI分別做說明。
?
?
C++中的RTTI機(jī)制
如果您翻閱C++ Builder所附的On-Line Help,您可找到下面這段對(duì)于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()運(yùn)算子來取得type_info的信息。此處應(yīng)當(dāng)注意的是typeid()是一個(gè)運(yùn)算子。他與sizeof() 是相同等級(jí)的運(yùn)算子。不過,若要使用typeid()您需要include typeinfo這個(gè)項(xiàng)目。您的include寫法如下:
?
#include <typeinfo>
using namespace std;
?
透過typeid()我們可以取得特定的型態(tài)的信息。例如,想要比較兩個(gè)變量是否為相同型態(tài)。您可以寫成下面的形式:
?
template <class T, class D>
bool isSameType(T var1, D var2)
{
??? return (typeid(var1) == typeid(var2));
}
?
這個(gè)函式可用來比較兩個(gè)變量的型態(tài)是否相等。
若您想取得型態(tài)的名稱。您可使用typeid()所傳回來的型態(tài)的name()函式。例如:
?
int a;
ShowMessage(typeid(int).name());
ShowMessage(typeid(a).name());
?
??? 若您想確認(rèn)兩者之間有無繼承關(guān)系,可使用typeid()所傳回來的型態(tài)中的before()函式。before()函式中有一個(gè)參數(shù)也是一個(gè)由 typeid()所傳回的型態(tài)信息。以前面的例子來說,若您想切確知道CShape是否在CRectangle之前(也就是是否CRectangle為 CShape的祖先),可用下面的程序來判斷:
?
if( typeid(CShape).before(typeid(CRectangle)) )
{
??? return true ;
}
?
??? 因此,當(dāng)您想要對(duì)一個(gè)class進(jìn)行up casting或是down casting時(shí),可先用這種方式判斷一下,兩者是否有繼承關(guān)系,然后才進(jìn)行轉(zhuǎn)換。當(dāng)然,這樣的檢查常常會(huì)用到,所以你可能打算把他寫成一個(gè)工具函式來用。不過,先等一下!標(biāo)準(zhǔn)的C++已經(jīng)幫您準(zhǔn)備好了!而且不只一個(gè),C++準(zhǔn)備了四個(gè)casting的工具函式,每一個(gè)都有不同的用法及意義。他們分別是:
const_cast<Type>(var)
const_cast是一個(gè)compile time的cast。其主要作用為移除或加上型態(tài)的 const 限制。舉例來說,您有一個(gè)const的整數(shù)a。您想要用一個(gè)整數(shù)指標(biāo)指向它。
?
??? const i = 0;
??? int *p = &i ; // Compile error! Cannot cast from const to violate.
?
但是您可能非常確定自己想要做什么,所以您可使用const_cast明確的告訴compiler做您要求的動(dòng)作。
?
??? const i = 0;
??? int *p = const_cast<int *>(&i) ; // OK.
?
同樣的,要把不具const性質(zhì)的型態(tài)轉(zhuǎn)成const性質(zhì)也是相同的方法。不過,請(qǐng)務(wù)必要知道自己為何這樣做,否則可能會(huì)惹上麻煩。
dynamic_cast<Type>(ptr)
在使用dynamic_cast時(shí),Type必需為指定為一個(gè)class的指標(biāo),否則就必需是void *。若為void *,則ptr所給定的指標(biāo)將會(huì)被轉(zhuǎn)換為void *,并且任何型態(tài)的指針內(nèi)。然而,真正常用的是用來進(jìn)行class的up casting或down casting。以前面的CShape及CRectangle而言,您可使用下面的方式進(jìn)行轉(zhuǎn)換:
?
??? CShape *sp = dynamic_cast<CShape *>( some_pointer );
??? CRectangle *rp = dynamic_cast<CRectangle *>(some_pointer);
?
或許,上面的范例看起來跟一般的static casting沒有什么差別。其實(shí),差別十分大,我們知道static casting的意思有點(diǎn)類似于強(qiáng)制要求compile幫您進(jìn)行轉(zhuǎn)換,所以不會(huì)顧形態(tài)與形態(tài)之間本身是否有繼承關(guān)系、是否真的可以轉(zhuǎn)換。所以稍不注意就常常會(huì)有Access Violation的狀況。但是dynamic_cast就不一樣了,他會(huì)幫您檢查并且確定來源的型態(tài)與目的型態(tài)是可進(jìn)行轉(zhuǎn)換的。若不能轉(zhuǎn)換就會(huì)傳回 NULL。所以您可以依據(jù)dynamic_cast的傳回值來判斷是否轉(zhuǎn)換成功。
reinterpret_cast<Type>(var)
其中Type必需為pointer, reference, arithmetic type, pointer to function或是pointer to member。reinterpret_cast可以幫您將整數(shù)轉(zhuǎn)變?yōu)橐粋€(gè)指向某種型態(tài)的指針。主要用于當(dāng)?shù)刂繁靥幚矸胖糜谡麛?shù)變量中。要將他轉(zhuǎn)回原來型態(tài)的指針時(shí)所使用。
static_cast<Type>(var)
就是我們一般以前常用的static casting的形式。只是為了與前面所介紹的三種casting匹配,而改成了這種形式。所以若您以前常用如下的方式進(jìn)行casting,不妨換種方式:
?
??? int a ;
??? float b = 10.01
??? a = static_cast<int>(b);
?
不確定轉(zhuǎn)換的指標(biāo)會(huì)不會(huì)與轉(zhuǎn)換后指針的型態(tài)兼容時(shí),請(qǐng)多多使用dynamic_cast。這樣可以避免預(yù)想不到的狀況發(fā)生。
?
?
VCL的RTTI機(jī)制
?
VCL所提供的RTTI機(jī)制,可以提供非常詳盡的信息。其大部分都供Borland C++ Builder或Delphi的Design環(huán)境使用。這也就是為何在Object Inspector可以看到對(duì)象的屬性(Property)及設(shè)定其Event了。只要您掌握了VCL上RTTI的精髓,您也可以寫出Object Inspector一樣的功能。
所謂的RTTI可視為用來記錄型態(tài)信息的一個(gè)Structure。這個(gè)部分是由VCL所提供。因此,要使用這些RTTI機(jī)制,大部分的狀況下必需作用于繼承自TObject的VCL組件。
我們要如何取得這個(gè)記載著型態(tài)信息的Structure呢?有幾種方式:
?
方法一
要取得一個(gè)VCL組件類別的信息可透過其ClassInfo()這個(gè)method。如果您看過VCL的對(duì)象階層圖,您就知道ClassInfo()這個(gè) method是在TObject內(nèi)定義的。所以,所有的VCL組件都可以使用他。仔細(xì)看一下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其實(shí)有兩個(gè),一種是TObject::ClassInfo()。另外一個(gè)是獨(dú)立的static function。其中,第一種適用于已經(jīng)有確定的instance。而在沒有instance的狀況下,就應(yīng)當(dāng)使用static function的方式。或者要問如何得到對(duì)應(yīng)某個(gè)class的TClass信息呢?您需要搭配VCL所提供的__classid這個(gè)關(guān)鍵詞。他可以取得特定class的TClass信息。例如:要取得TButton的RTTI信息,您需要使用下面的方式:
?
ClassInfo(__classid(TButton));
?
我們也看到ClassInfo()的傳回值是一個(gè)void *,這就是指向記載著RTTI信息結(jié)構(gòu)的指針。
除了ClassInfo(),其實(shí)還有另外一個(gè)方式,就是使用__typeinfo()這個(gè)宏。這個(gè)宏與ClassInfo()的作用相同。唯一的差別在于ClassInfo()傳回的是一個(gè)void *,而__typeinfo()會(huì)經(jīng)過一次的casting動(dòng)作轉(zhuǎn)成PTypeInfo的型態(tài),也就是TTypeInfo *的型態(tài)。
?
方法二
很不幸的一點(diǎn),前述的方式僅針對(duì)VCL的類別有作用。如果不是VCL類別就會(huì)有問題了。例如,某些類別看來很像VCL類別,實(shí)際上僅是一個(gè)列舉型態(tài)。就像是TAlign這個(gè)用來指定組件放置行為的型態(tài)。雖然也是T開頭。實(shí)際上不過就是個(gè)列舉型態(tài)罷了。所以,前面的方式都會(huì)讓您得到 compile error。在Delphi中,有一個(gè)名為TypeInfo的函式可以取得各種型態(tài)的TTypeInfo數(shù)據(jù)。但是,他主要的運(yùn)作是在compile time。這也就是說,你必需在compile time就指定好型態(tài)。所以,在BCB中的實(shí)用性不大。如果真的有必要。可以另外寫一個(gè)Delphi的程序文件,專門利用TypeInfo函式取得 TTypeInfo的數(shù)據(jù)。關(guān)于這個(gè)部分,建議您參考后面所提的『Run-Time Type Information(RTTI) In C++ Builder 5』一文。
?
方法三
如果您要存取的是非VCL類別的型態(tài),您可能要參考上面第二點(diǎn)的作法。不過,如果您要存取的是屬于某個(gè)VCL類別的__published節(jié)中的非 VCL類別型態(tài)。那么恭喜您!您未必需要搭配Delphi了。例如:您要取得TAlign這個(gè)型態(tài)的信息。所幸,在TPanel這個(gè)VCL組件中的 Align屬性就是TAlign的型態(tài)。而且Align是__published的。因?yàn)閂CL對(duì)于__published內(nèi)的東西一律會(huì)產(chǎn)生其RTTI 詳細(xì)信息。所以,我們就可以透過這種方式來存取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 信息后有何作用呢?
其實(shí),秘密都藏在$(BCB)\Source\VCL\typinfo.pas中。在這個(gè)檔案中存放了許多與VCL RTTI相關(guān)的信息及程序代碼。如果您對(duì)于Delphi或是Object Pascal不熟悉,沒關(guān)系,看看$(BCB)\Include\VCL\typinfo.hpp。這個(gè)是由BCB所自動(dòng)產(chǎn)生出來的include檔案。雖然沒有程序代碼在內(nèi)。但是,光看里面的定義,也大概可以猜出其作用為何。在此,我們將針對(duì)這個(gè)檔案內(nèi)所提供的數(shù)據(jù)結(jié)構(gòu)及相關(guān)函式進(jìn)行說明。
首先,我們來看看前面一直提到的TTypeInfo這個(gè)structure。您可在typinfo.hpp中找到他的定義。
?
struct TTypeInfo
{
??? TTypeKind Kind;
??? System::ShortString Name;
} ;
?
這個(gè)結(jié)構(gòu)非常簡單,只有兩個(gè)項(xiàng)目,其中TTypeKind是一個(gè)列舉型態(tài)。Kind記錄這是何種的型態(tài)。而Name則記載了該型態(tài)的名字。在VCL中針對(duì)TTypeKind的列舉型態(tài),共有下面這些項(xiàng)目:
列舉值 說明?
tkUnknown         保留,未使用的值。?
tkInteger         整數(shù)?
tkChar          Char或是AnsiChar的型態(tài)?
tkEnumeration      列舉型態(tài),包含Boolean, ByteBool, WordBool, LongBool及Bool?
tkFloat          浮點(diǎn)數(shù)?
tkString ShortString   型態(tài)?
tkSet Set         型態(tài)?
tkClass       ?    類別型態(tài)?
tkMethod          Procedure或是function型態(tài)?
tkWChar      ??   WideChar 型態(tài)?
tkLString     ????   WideString型態(tài)?
tkVariant      ?   Variant型態(tài)?
tkArray       ??  Array型態(tài)?
tkRecord      ??  Record型態(tài)(即struct)?
tkInterface     ??   Interface型態(tài)?
tkInt64       ?   Int64型態(tài)?
tkDynArray    ? ?動(dòng)態(tài)數(shù)組型態(tài)(即DynamicArray)?

??? 或許您會(huì)覺得奇怪,怎么好像一堆沒看過的型態(tài)。其實(shí),這些對(duì)應(yīng)的值都是Delphi中的型態(tài)。所以,您需要測(cè)試一下看看在BCB中,哪些型態(tài)會(huì)對(duì)應(yīng)到上面的項(xiàng)目。

有了上面這個(gè)信息,您就可以取得在VCL的型態(tài)信息,并且藉此來判斷所取得的型態(tài)為何。當(dāng)然未必所有的型態(tài)都可用Kind來加以判斷,此時(shí)建議您搭配Name一起來加以判斷,相信就可清楚的判斷出您要的型態(tài)了。
實(shí)際上,光是TTypeInfo的內(nèi)容是不夠用的,因?yàn)樗撬行蛻B(tài)共同的部分,針對(duì)其它屬于型態(tài)相關(guān)的信息,在TTypeInfo中是看不到的。若需要取得這些與個(gè)別型態(tài)相關(guān)的信息,就需要用到在TypInfo.hpp后面所記載的一些工具函式。首先,最重要的工具函式就是:
?
PTypeData __fastcall GetTypeData(PTypeInfo TypeInfo);
?
這個(gè)函式的參數(shù)為一個(gè)指向TTypeInfo的指標(biāo),透過這個(gè)TTypeInfo的信息,會(huì)傳回另一個(gè)指向TTypeData的指標(biāo)。這就是我們所要的個(gè)別型態(tài)的詳細(xì)數(shù)據(jù)。不幸的是,如果您去查鋁ypInfo.hpp中的訊息,您會(huì)發(fā)現(xiàn)到TTypeData其實(shí)是一堆struct的聯(lián)集。主要是因?yàn)椴煌男蛻B(tài)所需記錄的東西不同所致。
前面我們?cè)?jīng)提到透過BCB我們可以取得放在__published部分的屬性數(shù)據(jù)。那么,我們可以取得所有屬性的列表嗎?答案是可以的,只要他是放在__published中。要取得這個(gè)信息,您需要透過一些在TypInfo.hpp中所定義的函式的幫助。主要有幾個(gè)函式能夠幫助我們?nèi)〉脤傩缘男畔⑺麄兎謩e是:
?
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);
?
??? 簡單的說,如果你已經(jīng)很切確的知道自己所要找的是某個(gè)屬性,就請(qǐng)用GetPropInfo。如果您希望取得所有的屬性,可以使用GetPropInfos函式。如果您希望只取得屬于某種型態(tài)的屬性,或是對(duì)所取得的屬性進(jìn)行排序,建議使用GetPropList函式。
舉例來說,如果您要取得Form1中的Align屬性的型態(tài)信息。您可使用如下的程序代碼:
?
PPropInfo pi ;

pi = GetPropInfo(Form1->ClassInfo(), "Align");
?
若您希望取得某個(gè)VCL組件的所有屬性,可使用
?
TPropList List;
GetPropInfos(Form1->ClassInfo(),(PPropList)&List);
?
如果您想取得符合某些特定型態(tài)的屬性,可用:
?
TPropList List;
int Count = GetPropList((PTypeInfo)(Form1->ClassInfo()), tkAny, (PPropList)&List);
?
不過這里有個(gè)問題,如果您去看一下TPropList的定義,會(huì)發(fā)現(xiàn)他其實(shí)是一個(gè)非常大的指針數(shù)組。這樣內(nèi)存是蠻浪費(fèi)的,所以建議您可以換種方式:
?
int count = GetPropList((PTypeInfo)(Form1->ClassInfo()), tkAny, NULL);
PPropList list = new PPropInfo[count];
try {
??? GetPropList((PTypeInfo)ClassInfo(), tkAny, list);
}
__finally {
??? delete [ ] list ;
}
?
其中,TTypeKinds是用來記錄您期望符合的型態(tài)。他是一個(gè)Set的型態(tài)。舉例來說,如果您要取得整數(shù),浮點(diǎn)數(shù)這兩種型態(tài)。在TTypeKinds的部分可用下面的形式:
?
TTypeKinds() << tkInteger << tkFloat ;
?
如果您是BCB 5的使用者,這里請(qǐng)您要注意了,BCB 5在這個(gè)地方似乎有點(diǎn)問題,也就是說他的typinfo.hpp在這個(gè)地方的定義是錯(cuò)的。正確的定義應(yīng)該是下面這樣的:
?
#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是錯(cuò)的。建議您手動(dòng)將typinfo.hpp更正過來。
當(dāng)取得我們所要的屬性后,接下來的動(dòng)作就是要存取其屬性值。舉例來說,如果要設(shè)定某個(gè)bool型態(tài)的屬性為true,或者是取得其現(xiàn)在的屬性,該如何做呢?本來這是十分復(fù)雜的步驟,不過因?yàn)閠ypinfo.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);
?
?
取得與比較屬性的型態(tài):
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);
?
?
存取屬性(不管型態(tài)):
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);
?
?
存取整數(shù)型態(tài)屬性:
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);
?
?
存取浮點(diǎn)數(shù)型態(tài)屬性:
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);
?
?
存取列舉型態(tài)屬性:
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);
?
?
存取集合型態(tài)屬性:
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);
?
?
存取對(duì)象型態(tài)屬性:
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型態(tài)屬性:
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型態(tài)屬性:
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型態(tài)屬性:
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型態(tài)屬性:
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型態(tài)屬性:
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型態(tài)屬性:
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 這兩組函式就夠了。可是,除非您很熟悉 TTypeData 的細(xì)節(jié),否則建議您還是使用上述的這些與個(gè)別型態(tài)相關(guān)的函式吧。況且,Borland并未把上面的技術(shù)正式公布出來,其中的一個(gè)理由就是這些內(nèi)部結(jié)構(gòu)還有可能會(huì)修改。所以,還是別自己亂動(dòng)的好。另外一件事情就是,上面的函式未必所有C++ Builder的版本都有。建議您還是先看看自己的typinfo.hpp再說吧。

本文來自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/aniven/archive/2006/05/24/753200.aspx

轉(zhuǎn)載于:https://www.cnblogs.com/zhangdongsheng/archive/2011/04/10/2011008.html

總結(jié)

以上是生活随笔為你收集整理的BCB中的RTTI机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 精品无码久久久久成人漫画 | 欧美日韩综合一区 | 色综合精品 | 亚洲色图自拍 | 日本少妇久久 | 亚洲乱码国产乱码精品精98午夜 | 国产日产欧美 | 四虎网址在线观看 | 亚洲免费在线视频 | 日本男人天堂 | aaa成人| 亚洲国产精一区二区三区性色 | 精品午夜福利视频 | 一边摸一边做爽的视频17国产 | 国产在线欧美 | 日本中文字幕第一页 | 永久视频在线观看 | 久久精品免费观看 | 99热这里只有精品8 国产一卡二 | 日韩av男人的天堂 | 性欧美hd调教 | 在线激情网 | 欧美亚洲日本 | 欧美区一区二区三 | 天天躁狠狠躁狠狠躁夜夜躁68 | av国产精品 | 日韩精品播放 | 国产亚洲精品久久久久久 | 国精产品一二三区精华液 | 国产第一页在线播放 | 日韩欧美在线看 | 亚洲国产成人91porn | 日本黄色三级视频 | 成年人的免费视频 | 国产精品伊人久久 | 美女又爽又黄免费 | 午夜黄色| 黄色片免费播放 | 久久99久久99精品免观看粉嫩 | 啪视频网站| 免费看爱爱视频 | 不卡视频一区二区 | 最近免费中文字幕 | 免费观看久久 | 中国一级片黄色一级片黄 | 国产免费色视频 | 久久9999久久免费精品国产 | 精品人妻一区二区三区换脸明星 | 少妇无套内谢免费视频 | 深爱五月激情五月 | 国产精品99久久久久久久女警 | 婷婷成人综合网 | 无码人妻精品一区二区三应用大全 | 在线观看黄网 | 精品久久久视频 | 精品久久久久久久久久久久久久久 | 四虎色| av大帝在线观看 | 黄色天堂网站 | 日批免费网站 | 国产又粗又猛又色 | 免费成人黄色网 | 国产精品外围 | jizz性欧美2| 精品成在人线av无码免费看 | 久在线观看 | 久久久久久久久久99精品 | 91在线精品观看 | 亚洲天堂av在线免费观看 | 欧美国产日韩视频 | 大陆极品少妇内射aaaaaa | 日韩精品影视 | 国产色视频在线 | 婷婷六月在线 | 久久夜色精品国产欧美乱 | 国产精品国产三级国产aⅴ9色 | 1515hh成人免费看 | 欧洲av一区二区三区 | 国产午夜精品一区二区 | 打白嫩屁屁网站视频短裙 | 国产男女猛烈无遮挡免费视频动漫 | 夜夜操狠狠操 | 亚洲视频中文字幕在线观看 | 亚洲骚图| 欧美精品v国产精品v日韩精品 | 91黄在线看 | 日韩电影精品 | 手机av免费在线 | 日本91网站 | 黄色美女片 | 色com| 激情男女视频 | 黑人专干日本人xxxx | 男女靠逼视频 | 一区二区成人在线 | 亲嘴扒胸摸屁股免费视频日本网站 | 精品国产69 | 国产精品久久无码 | 欧美性受xxxx黒人xyx性爽 |