2009-12-31 4 views
102

में 'टाइपिड' बनाम 'टाइपऑफ' मैं सोच रहा हूं कि typeid और typeof के बीच सी ++ में अंतर क्या है। यहाँ मैं क्या पता है:सी ++

  • typeidtype_info के लिए दस्तावेज़ जो सी ++ हेडर फाइल typeinfo में परिभाषित किया गया है में उल्लेख किया है।

  • typeof सी के लिए जीसीसी एक्सटेंशन और सी ++ Boost लाइब्रेरी में परिभाषित किया गया है।

इसके अलावा, यहाँ है कि मैं मैं कहाँ की खोज की है typeid वापस नहीं करता कि मैं क्या उम्मीद बना लिया है परीक्षण कोड परीक्षण है। क्यूं कर?

main.cpp

#include <iostream> 
#include <typeinfo> //for 'typeid' to work 

class Person { 
    public: 
    // ... Person members ... 
    virtual ~Person() {} 
}; 

class Employee : public Person { 
    // ... Employee members ... 
}; 

int main() { 
    Person person; 
    Employee employee; 
    Person *ptr = &employee; 
    int t = 3; 

    std::cout << typeid(t).name() << std::endl; 
    std::cout << typeid(person).name() << std::endl; // Person (statically known at compile-time) 
    std::cout << typeid(employee).name() << std::endl; // Employee (statically known at compile-time) 
    std::cout << typeid(ptr).name() << std::endl;  // Person * (statically known at compile-time) 
    std::cout << typeid(*ptr).name() << std::endl;  // Employee (looked up dynamically at run-time 
                 // because it is the dereference of a pointer 
                 // to a polymorphic class) 
} 

उत्पादन:

bash-3.2$ g++ -Wall main.cpp -o main 
bash-3.2$ ./main 
i 
6Person 
8Employee 
P6Person 
8Employee 
+6

किस तरह से आपको लगता है अपने कोड सही प्रकार नाम प्रिंट नहीं करता हो? यह मुझे अच्छा लग रहा है। 'Name()' द्वारा लौटाई गई वास्तविक स्ट्रिंग कार्यान्वयन-परिभाषित है। यह वैध सी ++ पहचानकर्ता नाम नहीं होना चाहिए, बस * कुछ * जो विशिष्ट रूप से प्रकार की पहचान करता है। ऐसा लगता है कि आपका कार्यान्वयन कंपाइलर के सामान्य नाम-मैंगलिंग योजना का उपयोग करता है। –

+0

धन्यवाद रॉब! मैं उन लोगों के नामों की अपेक्षा कर रहा था जैसा कि मैंने en.wikipedia.org/wiki/Typeid में देखा था। नाम-मैंगलिंग क्या कर सकता है? – Tim

उत्तर

139

C++ भाषा typeof जैसी कोई चीज नहीं है। आपको कुछ कंपाइलर-विशिष्ट एक्सटेंशन को देखना होगा। यदि आप जीसीसी के typeof के बारे में बात कर रहे हैं, तो एक समान सुविधा C++ 11 में कीवर्ड decltype के माध्यम से मौजूद है। दोबारा, सी ++ में ऐसा कोई typeof कीवर्ड नहीं है।

typeid एक सी ++ भाषा ऑपरेटर है जो रन टाइम पर टाइप पहचान जानकारी देता है। यह मूल रूप से type_info ऑब्जेक्ट देता है, जो अन्य type_info ऑब्जेक्ट्स के साथ समानता-तुलनीय है।

ध्यान दें, लौटे type_info वस्तु का केवल परिभाषित संपत्ति है कि अपनी किया जा रहा equality- और गैर समानता-बराबर है, यानी type_info विभिन्न प्रकार का वर्णन करते हुए की तुलना गैर-बराबर जबकि type_info वस्तुओं एक ही प्रकार का वर्णन वस्तुओं के लिए है बराबर की तुलना करें। बाकी सब कुछ कार्यान्वयन-परिभाषित है। विभिन्न "नाम" वापस करने वाले तरीके मानव-पठनीय कुछ भी वापस करने की गारंटी नहीं देते हैं, और यहां तक ​​कि कुछ भी वापस करने की गारंटी भी नहीं है।

यह भी ध्यान रखें, कि इसके बाद के संस्करण शायद का तात्पर्य (हालांकि मानक प्रतीत नहीं होता है स्पष्ट रूप से इसे का उल्लेख) है कि एक ही प्रकार के लिए typeid की लगातार अनुप्रयोगों अलग type_info वस्तुओं वापस कर सकती है (बेशक, अभी भी बराबर की तुलना करने के लिए है जो,)।

+0

धन्यवाद, एंड्रीटी! मैंने अभी कुछ नए प्रश्नों के साथ पोस्ट अपडेट किया है। यदि संभव हो तो कृपया एक नज़र डालें। – Tim

+0

को सी ++ 11 में 'decltype' के बाद से अपडेट की आवश्यकता नहीं होगी? मुझे यकीन नहीं है कि सामान्य नीति क्या है, लेकिन जैसा कि प्रश्न 'सी ++' टैग किया गया है, मैं उम्मीद करता हूं कि यह नवीनतम मानक को संदर्भित करे। प्रश्न को पुनः प्राप्त करना 'सी ++ 03' के रूप में भी एक विकल्प होगा। मैं व्यक्तिगत रूप से कभी-कभी काफी भ्रमित हो जाता हूं, क्योंकि मुझे काम पर प्रीसी ++ 11 का उपयोग करना पड़ता है और कभी-कभी मुझे यकीन नहीं है कि "pre11" या "post11" क्या सच है। – user463035818

+0

एफवाईआई, 'decltype'' typeof' के लिए प्रतिस्थापन नहीं है। 'टाइप टाइप' 'टाइपटाइप' के दौरान भी प्रकारों पर काम करता है। उदाहरण के लिए, 'टाइपऑफ (int)' 'int' है जबकि' decltype (int) 'एक त्रुटि है। – Shahbaz

34

दो के बीच प्राथमिक अंतर पीछा कर रहा है

  • typeof एक संकलन समय निर्माण और रिटर्न है जैसा परिभाषित किया गया प्रकार संकलन समय
  • टाइपिड एक रनटाइम निर्माण है और इसलिए मूल्य के रनटाइम प्रकार के बारे में जानकारी देता है।

typeof Refenence: http://www.delorie.com/gnu/docs/gcc/gcc_36.html

typeid Rfeerence: http://en.wikipedia.org/wiki/Typeid

+0

धन्यवाद, जेरेडपार! आपके उत्तरों को पढ़ने के बाद अपडेट किए गए पोस्ट में मेरे कुछ नए प्रश्न हैं। जैसे कि यह भी सच है कि उनके रिटर्न का उपयोग विभिन्न उद्देश्यों के लिए किया जाता है: टाइपफ़ोफ की वापसी प्रकार के कीवर्ड के रूप में उपयोग की जाती है जो परिवर्तनीय परिभाषित कर सकती है, लेकिन टाइपिड की वापसी नहीं हो सकती है? – Tim

23

typeid रनटाइम पर काम कर सकते हैं, और एक वस्तु वस्तु का प्रयोग समय प्रकार का वर्णन है, जिनमें से एक वस्तु के लिए सूचक होना चाहिए वापसी कक्षा में संग्रहीत करने के लिए RTTI (run-time type information) के लिए वर्चुअल विधियों वाला एक वर्ग। यह संकलन समय प्रकार को अभिव्यक्ति या प्रकार का नाम भी दे सकता है, अगर रन-टाइम प्रकार की जानकारी वाले क्लास को पॉइंटर नहीं दिया जाता है।

typeof एक जीएनयू एक्सटेंशन है, और आपको संकलन समय पर किसी भी अभिव्यक्ति का प्रकार देता है। यह उपयोगी हो सकता है, उदाहरण के लिए, मैक्रोज़ में अस्थायी चर घोषित करने में जो कई प्रकारों पर उपयोग किया जा सकता है। सी ++ में, आप आमतौर पर templates का उपयोग करेंगे।

+4

जहां तक ​​मुझे पता है, 'टाइपिड' किसी भी अभिव्यक्ति को स्वीकार नहीं करेगा, न केवल उन लोगों के लिए जो वर्चुअल विधियों के साथ ऑब्जेक्ट का मूल्यांकन करते हैं। इसके अलावा, 'टाइपिड' एक प्रकार * नाम * स्वीकार करेगा, केवल एक अभिव्यक्ति नहीं। यदि आप चाहें तो 'टाइपिड (5)' या 'टाइपिड (std :: string)' कह सकते हैं। –

+1

मैंने इसे स्पष्ट करने के लिए अपना उत्तर स्पष्ट कर दिया है; 'टाइपिड * * उपलब्ध होने पर रन-टाइम प्रकार की जानकारी लौटा सकता है, लेकिन किसी और चीज के लिए संकलित समय प्रकार की जानकारी प्रदान करेगा। –

+0

धन्यवाद, ब्रायन और रोब!आपके उत्तरों को पढ़ने के बाद अपडेट किए गए पोस्ट में मेरे कुछ नए प्रश्न हैं। – Tim

19

अतिरिक्त प्रश्न का उत्तर देना:

मेरी निम्नलिखित typeid के लिए परीक्षण कोड नहीं उत्पादन सही प्रकार नाम से करता है। क्या गलत है?

कुछ भी गलत नहीं है। आप जो देखते हैं वह प्रकार के नाम का स्ट्रिंग प्रस्तुति है। मानक सी ++ कक्षा के सटीक नाम को उत्सर्जित करने के लिए कंपाइलर्स को मजबूर नहीं करता है, यह तय करने के लिए कि क्या उपयुक्त है, यह केवल कार्यान्वयनकर्ता (कंपाइलर विक्रेता) पर निर्भर करता है। संक्षेप में, नाम कंपाइलर तक हैं।


ये दो अलग-अलग टूल्स हैं।typeof एक अभिव्यक्ति के प्रकार को लौटाता है, लेकिन यह मानक नहीं है। सी ++ 0x में decltype नामक कुछ है जो एक ही काम AFAIK करता है।

decltype(0xdeedbeef) number = 0; // number is of type int! 
decltype(someArray[0]) element = someArray[0]; 

typeid जबकि बहुरूपी प्रकार के साथ प्रयोग किया जाता है। उदाहरण के लिए, मान लीजिए कि कि cat निकला animal:

animal* a = new cat; // animal has to have at least one virtual function 
... 
if(typeid(*a) == typeid(cat)) 
{ 
    // the object is of type cat! but the pointer is base pointer. 
} 
+0

धन्यवाद, अराक! मैंने अभी कुछ नए प्रश्नों के साथ पोस्ट अपडेट किया है। यदि संभव हो तो कृपया एक नज़र डालें। – Tim

2

आप एक अच्छा देख नाम पूरा करने के लिए बूस्ट demangle उपयोग कर सकते हैं: जैसे

To_main_msg_evt ev("Failed to initialize cards in " + boost::units::detail::demangle(typeid(*_IO_card.get()).name()) + ".\n", true, this); 
4

typeid कार्यावधि में डेटा के प्रकार प्रदान करता है

#include <boost/units/detail/utility.hpp> 

और कुछ, जब के लिए कहा। Typedef एक संकलन समय निर्माण है जो उसके बाद बताए गए एक नए प्रकार को परिभाषित करता है। C++ कोई typeof आउटपुट के रूप में प्रकट होता है (खुदा टिप्पणी के रूप में दिखाया गया है) नहीं है:

std::cout << typeid(t).name() << std::endl; // i 
std::cout << typeid(person).name() << std::endl; // 6Person 
std::cout << typeid(employee).name() << std::endl; // 8Employee 
std::cout << typeid(ptr).name() << std::endl;  // P6Person 
std::cout << typeid(*ptr).name() << std::endl;  //8Employee