C ++ में 'टाइपिड' बनाम 'टाइपोफ'


159

मैं सोच रहा हूँ क्या अंतर के बीच है typeidऔर typeofसी ++ में। यहाँ मुझे पता है:

  • typeidप्रलेखन में type_info के लिए उल्लेख किया गया है जो C ++ हैडर फ़ाइल टाइपिनफो में परिभाषित है ।

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

इसके अलावा, यहां टेस्ट कोड टेस्ट है जो मैंने बनाया है, जहां मैंने पाया है कि 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

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

धन्यवाद रोब! जैसा कि मैंने en.wikipedia.org/wiki/Typeid में देखा था, मैं ठीक उसी तरह के नामों की उम्मीद कर रहा था। यहाँ नाम-पण्य क्या कर सकते हैं?
टिम

यदि आप मेरी तरह टाइप करने के लिए नए हैं: तो आपको vable को चालू करने के लिए बेस टाइप में वर्चुअल फंक्शन की जरूरत है या आखिरी लाइन बेस टाइप को प्रिंट करेगी।
jw_

जवाबों:


200

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

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

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

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


1
C ++ 11 के बाद से इसे अपडेट की आवश्यकता नहीं होगी decltype? मुझे यकीन नहीं है कि सामान्य नीति क्या है, लेकिन जैसा कि प्रश्न टैग किया गया है, C++मैं उम्मीद करूंगा कि यह नवीनतम मानक का उल्लेख करेगा। प्रश्न को C++03फिर से समझना भी एक विकल्प होगा। मैं व्यक्तिगत रूप से कभी-कभी काफी भ्रमित हो जाता हूं, क्योंकि मुझे काम पर प्रीसी ++ 11 का उपयोग करना पड़ता है और कभी-कभी मुझे यकीन नहीं होता है कि क्या सच है "प्री 11" या "पोस्ट 11"।
आईडीक्लेव ४६३०३५18१

11
FYI, के decltypeलिए एक प्रतिस्थापन नहीं है typeoftypeofप्रकार पर भी काम करता है, जबकि decltypeनहीं करता है। उदाहरण के लिए, typeof(int)है int, जबकि decltype(int)एक त्रुटि है।
शहबाज

1
" type_infoविभिन्न प्रकारों का वर्णन करने वाली वस्तुएं गैर-बराबर की तुलना करेंगी" । वास्तव में, यह गारंटी नहीं है । असमानता ऑपरेटर को C ++ 20 में हटा दिया गया था (मुझे लगता है) गैर-बराबर की तुलना करने वाले विभिन्न प्रकारों पर निर्भर हतोत्साहित करता है। लेकिन अगर आप इसके बारे में सोचते हैं, अगर असमानता सुरक्षित नहीं है तो समानता सुरक्षित नहीं है।
इंडियाना कर्निक

51

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

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

टाइपोफ़ संदर्भ: http://www.delorie.com/gnu/docs/gcc/gcc_36.html

टाइपिड संदर्भ: https://en.wikipedia.org/wiki/Typeid


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

26

typeidरनटाइम पर काम कर सकते हैं, और ऑब्जेक्ट को रन टाइम प्रकार का वर्णन करते हुए लौटा सकते हैं, जो कक्षा में संग्रहित होने के लिए आरटीटीआई (रन-टाइम प्रकार की जानकारी) के लिए वर्चुअल तरीकों के साथ एक कक्षा के ऑब्जेक्ट के लिए एक संकेतक होना चाहिए । यह संकलित समय प्रकार की अभिव्यक्ति या एक प्रकार का नाम भी दे सकता है, अगर रन-टाइम प्रकार की जानकारी के साथ एक कक्षा को एक संकेतक नहीं दिया जाता है।

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


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

1
मैंने अपना उत्तर स्पष्ट कर दिया है; यदि उपलब्ध हो तो रन-टाइम प्रकार की जानकारी वापस typeid कर सकते हैं, लेकिन किसी अन्य चीज़ के लिए संकलन समय की जानकारी प्रदान करेंगे।
ब्रायन कैंपबेल

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

22

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

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

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


ये दो अलग-अलग उपकरण हैं। typeofएक अभिव्यक्ति का प्रकार लौटाता है, लेकिन यह मानक नहीं है। C ++ 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.
}

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

4

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

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

3

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

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

और कुछ इस तरह

To_main_msg_evt ev("Failed to initialize cards in " + boost::units::detail::demangle(typeid(*_IO_card.get()).name()) + ".\n", true, this);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.