2012-06-30 9 views
6

जैसा कि मैंने here पढ़ा है एक वर्ग की इकाई का नाम प्राप्त कर सकते हैंमैं कैसे, अगर मैं वर्ग/VMT पता ही

VMT भी "जादू" क्षेत्रों के एक नंबर जैसे सुविधाओं समर्थन करने के लिए होता है माता पिता वर्ग लिंक, उदाहरण के आकार, वर्ग के नाम, गतिशील विधि मेज, प्रकाशित तरीकों की मेज, प्रकाशित क्षेत्रों मेज, RTTI मेज, जादू क्षेत्रों के लिए प्रारंभ मेज, पदावनत OLE स्वचालन प्रेषण तालिका और कार्यान्वित इंटरफेस तालिका

ऐसा लगता है कि वीएमटी में ऐसे क्षेत्र को शामिल नहीं किया गया है जिसमें यूनिट का नाम है जहां वर्ग परिभाषित किया गया है। क्या कुछ 'कंपाइलर जादू' शामिल है?

उत्तर

9

मैं नहीं देख सकता कि वीएमटी यहां क्यों शामिल होना चाहिए। TObject पहले से ही class function UnitName का खुलासा करता है।

System.TObject.UnitName

+9

डी 200 9 से पहले के संस्करणों के लिए, कोई 'typinfo.GetTypeData (TSomeClass.ClassInfo) का उपयोग कर सकता है। UnitName' –

1

VMT वर्ग RTTI के लिए सूचक (ClassInfo विधि द्वारा प्रदान की) भी शामिल है, कक्षा आरटीटीआई में एक वर्ग इकाई का नाम शामिल है। एक अभ्यास के रूप में आप VMT सूचक से इकाई का नाम प्राप्त कर सकते हैं, मैं इस में लिखा है (डेल्फी XE पर परीक्षण):

uses TypInfo; 

type 
    TObj = class 

    end; 

procedure TForm1.Button3Click(Sender: TObject); 
var 
    Obj: TObj; // dummy obj instance 
    VMT: Pointer; 
    P: Pointer; // class info 

begin 
// you can get VMT pointer so 
    Obj:= TObj.Create; 
    VMT:= PPointer(Obj)^; 
    Obj.Free; 
// or so 
    VMT:= Pointer(TObj); 

    P:= PPointer(PByte(VMT) + vmtTypeInfo)^; 
    if P <> nil then 
    ShowMessage(GetTypeData(P).UnitName); 
end; 
+2

चूंकि, जैसा कि आप उल्लेख करते हैं, आरटीटीआई सूचक' क्लासइन्फो 'विधि से उपलब्ध है, आप ऐसे सर्किट का प्रदर्शन क्यों करते हैं एक ही जानकारी प्राप्त करने के लिए मार्ग? आप बस उस कोड को 'पी: = TObj.ClassInfo' के साथ बदल सकते हैं। –

+0

@ रोबकेनेडी - आप 'क्लासइन्फो' विधि को सीधे अज्ञात वर्ग के वीएमटी के लिए केवल एक सूचक होने पर कॉल नहीं कर सकते हैं। आप किसी भी तरह से वीएमटी पॉइंटर टाइपकास्ट करने का प्रयास कर सकते हैं, लेकिन मुझे यह नहीं मिला है कि इसे कैसे किया जाए। – kludg

+4

@ सर्ग बस वीएमटी पॉइंटर को 'टी क्लास' पर डालें। फिर आप एक-लाइनर बना सकते हैं: 'TypInfo.GetTypeData (TClass (vmt) .ClassInfo) .UnitName' –

0
procedure MessageException(E: Exception); 
var 
    TI: TypInfo.PTypeInfo; 
begin 
    TI := E.ClassInfo; 
    if Assigned(TI) then 
    begin 
    Dialogs.MessageDlg(TypInfo.GetTypeData(TI).UnitName + '.' + 
     E.ClassName + ': ' + E.Message, Dialogs.mtError, [Dialogs.mbOK], 0, Dialogs.mbOK); 
    end 
    else 
    begin 
    Dialogs.MessageDlg(E.ClassName + ': ' + E.Message, Dialogs.mtError, [Dialogs.mbOK], 0, Dialogs.mbOK); 
    end; 
end; 

ध्यान दें कि ClassInfo के लिए शून्य परीक्षण किया जाना चाहिए। जैसे SysUtils.ERangeError यह नहीं है।

संबंधित मुद्दे