2014-10-12 10 views
7

क्या है, मैं जानना चाहता हूं कि आधुनिक सी ++ 11 जावा के उदाहरण के बराबर क्या है। मैंने यह SO post देखा है लेकिन यह काफी पुराना है और क्या सोच रहा था कि सी ++ 11 में अधिक आधुनिक, बेहतर समाधान है या नहीं?सी ++ 11 के जावा के उदाहरण के समतुल्य

मुझे आशा थी कि मैन्युअल एनम क्लास का उपयोग किए बिना स्विच निर्माण का उपयोग करने की संभावना है।

class A { 

}; 

class B : public A { 

} 

class C : public A { 

} 

on_event(A& obj) 
{ 
    switch (obj) { 
     case A: 
     case B: 
     case C: 
    } 
} 

मेरी बेस क्लास में कोई वर्चुअल विधियां या फ़ंक्शन नहीं हैं। मैं एक पार्सर के लिए एक अभिव्यक्ति वृक्ष का प्रतिनिधित्व कर रहा हूं और बेस क्लास सिर्फ एक पॉलिमॉर्फिक धारक है - जैसे हास्केल/ओकैमल में एडीटी।

+3

क्या आप 'dynamic_cast <>' के लिए पूछ रहे हैं? यह सी ++ 11 विशिष्ट नहीं है। –

+0

कुछ भी नहीं बदला: मानक सी ++ में कोई प्रतिबिंब नहीं है। यदि आप रनटाइम प्रकार की जानकारी पर स्विच करना चाहते हैं, तो आप 'dynamic_cast' – quantdev

+0

रुचि के हो सकते हैं: http://stackoverflow.com/q/25495733/596781 –

उत्तर

12

एक ही जवाब अभी भी लागू होता है, और हमेशा C++ इस तरह किया गया है:

if (C * p = dynamic_cast<C *>(&obj)) 
{ 
    // The type of obj is or is derived from C 
} 
else 
{ 
    // obj is not a C 
} 

इस निर्माण A की आवश्यकता है बहुरूपी हो सकता है, अर्थात आभासी सदस्य कार्य करने के लिए।

यह भी ध्यान रखें कि इस व्यवहार जावा के instanceof रूप typeid(obj) == typeid(C) तुलना, ठीक वैसी ही पहचान के लिए बाद परीक्षण के बाद से, जबकि गतिशील डाली, साथ ही से अलग है, केवल लक्ष्य प्रकार के लिए परीक्षण के प्रकार के आधार वर्ग होने के लिए सबसे व्युत्पन्न वस्तु।

+1

इसे 'आरटीटीआई' की भी आवश्यकता है, जो कि कुछ सी ++ उपयोगकर्ताओं के लिए दर्द का दर्द है। – user2485710

+1

@ user2485710: मुझे नहीं लगता कि यह बयान * भाषा * सी ++ के संदर्भ में समझ में आता है। योग्यता के बिना कोड मान्य सी ++ है। –

+1

यदि आपके पास 'RTTI' नहीं है, तो यह काम काम नहीं करेगा, इससे कोई फर्क नहीं पड़ता कि आप क्या सोच रहे हैं, कोड की उस टुकड़े को सही तरीके से काम करने के लिए बस जरूरी है। – user2485710

-1

आप संकलन समय पर जाना जाता है प्रकार तक सीमित करने के लिए तैयार (बजाय vtables साथ कक्षाओं के उदाहरण पर संकेत के माध्यम से काम) कर रहे हैं - एक instanceof बराबर है तो सी ++ 11 और बाद में: यह std::is_base_of है।

आप std::is_convertible और std::is_same देख सकते हैं।

+3

मुझे यकीन नहीं है कि वह उसे कैसे मदद करता है जब तक कि वह इसे फ़ंक्शन टेम्पलेट नहीं बनाता है और संकलन-समय पर प्रकारों को जानता है। मुझे लगता है कि यह बहुत स्पष्ट है कि वह रनटाइम पॉलीमोर्फिज्म – PeterT

+0

@ पीटरटर के बारे में बात कर रहा है: पूरी तरह से असहमत। यही है, सी ++ में, विशेष रूप से आधुनिक सी ++ में, हम संकलन-समय-ज्ञात प्रकारों के साथ बहुत कुछ करते हैं, इसलिए यह एक पूरी तरह से वैध उत्तर है (भले ही इसे संपादित किया जाना चाहिए)। – einpoklum

0

सी ++ सादे पुराने डेटा (पीओडी) में कोई रनटाइम प्रकार की जानकारी नहीं है। वर्णित कक्षाएं सभी 1 बाइट लेती हैं, और खाली बेस क्लास ऑप्टिमाइज़ेशन वाले किसी भी कंपाइलर में समान रनटाइम प्रस्तुतिकरण होते हैं।

जैसा कि आप चाहते हैं कि नहीं किया जा सकता है।

बेस क्लास में वर्चुअल विनाशक जोड़ना आरटीटीआई में जोड़ता है, और dynamic_cast समर्थन।

enum या int फ़ील्ड को उस आधार पर जोड़ना जो प्रत्येक व्युत्पन्न वर्ग के लिए अलग-अलग प्रारंभ होता है।

using my_type_id=void(*)(); 
template<class>void get_my_type_id_helper(){}; 
template<class T> my_type_id get_my_type_id(){return get_my_type_id_helper<T>;} 

और फिर एक A उचित रूप से प्रारंभ में my_type_id भंडारण:

फिर भी एक और विकल्प तो जैसे एक टेम्पलेट समारोह बनाते हैं, और यह करने के लिए एक सूचक स्टोर करने के लिए, है। यह आरटीटीआई को पुनर्निर्मित कर रहा है, और जैसा कि आप अधिक सुविधाएं चाहते हैं, आप सी ++ आरटीटीआई ओवरहेड से संपर्क करेंगे।

सी ++ में आप केवल जो मांगते हैं उसके लिए भुगतान करते हैं: आप आरटीटीआई के बिना कक्षाओं के लिए पूछ सकते हैं, जो आपने किया था, और इसे प्राप्त किया।

आरटीटीआई रन टाइम टाइप जानकारी है। पीओडी सादा पुराना डेटा है, एक सी ++ 03 शब्द। कई कक्षाएं पीओडी नहीं हैं: virtual विनाशक जोड़ने का आसान तरीका है। सी ++ 11 में अधिक बढ़िया मानक लेआउट और कुल शर्तें हैं।

तकनीकी रूप से आरटीटीआई और पीओडी एक दूसरे के विरोध नहीं हैं: ऐसे आरटीटीआई वाले वर्ग हैं जो पीओडी नहीं हैं।

ध्यान दें कि एमएसवीसी के पास आरटीटीआई उत्पन्न करने के विकल्प नहीं हैं और इसके आक्रामक कॉमडैट फोल्डिंग मानक के उल्लंघन में दोनों मामलों में मैन्युअल आरटीटीआई को तोड़ सकते हैं।

-1

ऐसा मत करो। ज्यादातर मामलों में आपको instanceof या dynamic_cast के लिए पूछते समय अपने डिज़ाइन की समीक्षा करनी चाहिए।

क्यों? आप सबसे अधिक संभावना Liskov's substitiontin principle का उल्लंघन कर रहे हैं।

इस दृष्टिकोण के बारे में कैसे:

class A { 
    public: 
    virtual void action(); 
    virtual ~A(); 
}; 

class B : public A { 
    public: void action() override; 
}; 

class C : public A { 
    public: void action() override; 
}; 

void on_event(A& obj) 
{ 
    obj.action(); 
} 

ध्यान दें कि के रूप में @Yakk ने बताया आप कम से कम एक virtual विधि वैसे भी गतिशील बहुरूपता प्राप्त करने की आवश्यकता। और एक नियम है जो कहता है: जब आपके पास कम से कम एक वर्चुअल विधि होती है, तो हमेशा बेस क्लास में आभासी विनाशक भी लिखें।

आप यह सब टेम्पलेट्स और विशेषज्ञता के साथ कर सकते हैं या टैगिंग टाइप कर सकते हैं लेकिन मैं आपके प्रश्न से लेता हूं - जावा से आ रहा है - आप अभी तक वहां नहीं जाना चाहते हैं। आप वास्तव में वर्चुअल विधियों की तरह हैं, है ना? क्षमा करें, आपको उन्हें C++ में चिह्नित करना होगा।

+0

मुझे नहीं लगता कि एक प्रोग्राम जिसमें 3 कक्षाएं (ए, बी, सी) शामिल हैं, एलएसपी का उल्लंघन करती है और इसे एक अच्छी डिजाइन के रूप में माना जा सकता है। मैं डाउनवोट करना चाहता था क्योंकि एलएसपी भाग गुमराह कर रहा है (सवाल सी ++ 11 के उदाहरण के प्रत्यक्ष विकल्प के बारे में है और आपकी चेतावनियों का लिंक पहले से ही उल्लेख किया गया है), लेकिन किसी को यह उपयोगी लगेगा। – m039

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