जावा के उदाहरण के C ++ के बराबर


202

जावा के सी ++ के बराबर प्राप्त करने के लिए पसंदीदा तरीका क्या है instanceof?


57
प्रदर्शन और अनुकूलता के कारण ...
युवल एडम

7
यह पूछने के लिए उचित नहीं है "किस भाषा में - उदाहरण?"
मिस्टिककॉडर

3
@mysticcoder: मुझे बल्गेरियाई के लिए "например на" मिला, GT C ++ का समर्थन नहीं करता है
मार्क के कोवान

जवाबों:


200

प्रयोग करके देखें:

if(NewType* v = dynamic_cast<NewType*>(old)) {
   // old was safely casted to NewType
   v->doSomething();
}

इसके लिए आपके कंपाइलर को आरटीआई सपोर्ट सक्षम होना चाहिए।

संपादित करें: मैंने इस उत्तर पर कुछ अच्छी टिप्पणियां की हैं!

हर बार जब आपको एक डायनामिक_कास्ट (या इंस्टाफॉफ़) का उपयोग करने की आवश्यकता होती है, तो आप बेहतर ढंग से खुद से पूछेंगे कि क्या यह एक आवश्यक चीज है। यह आमतौर पर खराब डिजाइन का संकेत है।

विशिष्ट वर्कआर्ड्स उस वर्ग के लिए विशेष व्यवहार डाल रहा है जिसे आप बेस क्लास पर वर्चुअल फ़ंक्शन में देख रहे हैं या शायद आगंतुक की तरह पेश कर रहे हैं कर रहे हैं जहां आप इंटरफ़ेस को बदले बिना उपवर्गों के लिए विशिष्ट व्यवहार का परिचय दे सकते हैं (आगंतुक स्वीकृति इंटरफ़ेस जोड़ने के अलावा) पाठ्यक्रम)।

जैसा कि बताया गया है कि dynam_cast मुफ्त में नहीं आता है। एक सरल और लगातार प्रदर्शन करने वाली हैक जो सबसे अधिक (लेकिन सभी मामलों को नहीं संभालती है) मूल रूप से एक Enum जोड़ रही है जो आपके वर्ग के सभी संभावित प्रकारों का प्रतिनिधित्व कर सकती है और जांच सकती है कि क्या आपको सही मिला है।

if(old->getType() == BOX) {
   Box* box = static_cast<Box*>(old);
   // Do something box specific
}

यह अच्छा ओओ डिज़ाइन नहीं है, लेकिन यह एक वर्कअराउंड हो सकता है और इसकी लागत कम या ज्यादा केवल एक वर्चुअल फंक्शन कॉल है। यह आरटीटीआई के सक्षम या न होने के बावजूद भी काम करता है।

ध्यान दें कि यह दृष्टिकोण वंशानुक्रम के कई स्तरों का समर्थन नहीं करता है, इसलिए यदि आप सावधान नहीं हैं तो आप इस तरह दिखने वाले कोड के साथ समाप्त हो सकते हैं:

// Here we have a SpecialBox class that inherits Box, since it has its own type
// we must check for both BOX or SPECIAL_BOX
if(old->getType() == BOX || old->getType() == SPECIAL_BOX) {
   Box* box = static_cast<Box*>(old);
   // Do something box specific
}

4
आम तौर पर ऐसा होता है जब आप "
इंस्टाफ़ॉ

7
यदि आपको इंस्टॉफ़ का उपयोग करना है, तो ज्यादातर मामलों में, आपके डिज़ाइन में कुछ गड़बड़ है।
mslot

24
यह न भूलें कि डायनामिक_कास्ट बड़ी लागत के साथ एक ऑपरेशन है।
Klaim

13
गतिशील प्रकार के परीक्षण के उचित उपयोग के कई उदाहरण हैं। यह आमतौर पर पसंद नहीं किया जाता है, लेकिन इसकी एक जगह है। (अन्यथा, यह क्यों या इसके समकक्ष हर प्रमुख ओओ-भाषा में दिखाई देगा: सी ++, जावा, पायथन, आदि?)
पॉल ड्रेपर

2
मैं दोनों IOException स्तर पर पकड़ लेगा, अगर उन्हें अलग ढंग से नियंत्रित करने की आवश्यकता नहीं है। अगर उन्हें अलग ढंग से संभालने की जरूरत है, तो मैं प्रत्येक अपवाद के लिए एक कैच ब्लॉक जोड़ूंगा।
mslot

37

आप जो करना चाहते हैं उसके आधार पर आप यह कर सकते हैं:

template<typename Base, typename T>
inline bool instanceof(const T*) {
    return std::is_base_of<Base, T>::value;
}

उपयोग:

if (instanceof<BaseClass>(ptr)) { ... }

हालांकि, यह पूरी तरह से संकलक द्वारा ज्ञात प्रकारों पर संचालित होता है।

संपादित करें:

यह कोड बहुरूपी बिंदुओं के लिए काम करना चाहिए:

template<typename Base, typename T>
inline bool instanceof(const T *ptr) {
    return dynamic_cast<const Base*>(ptr) != nullptr;
}

उदाहरण: http://cpp.sh/6qir


सुरुचिपूर्ण और अच्छी तरह से किया गया घोल। +1 लेकिन सही पॉइंटर पाने के लिए सावधान रहें। पॉलीमोर्फिक पॉइंटर के लिए मान्य नहीं है?
एड्रियन मैयर

यदि इस फ़ंक्शन का उपयोग करते समय हमने पॉइंटर को स्थगित कर दिया तो क्या होगा? यह तो बहुरूपी संकेत के लिए काम करेगा?
mark.kedzierski

यह केवल संकलक के लिए ज्ञात प्रकारों पर ही संचालित होता है। पॉलीमॉर्फिक पॉइंटर्स के साथ काम नहीं करेंगे, भले ही आप डेरेफेरेंस करें या न करें। मैं कुछ है कि हालांकि उस मामले में काम कर सकते हैं जोड़ देंगे।
पैन्ज़ी

2
मैंने इस पद्धति के एक संस्करण को लिखने के लिए आपके उदाहरण को संशोधित किया है जो संकेत के बजाय संदर्भ का उपयोग करता है: cpp.sh/8owv
श्री हर्ष चिलकापति

डायनेमिक कास्ट "कॉन्स्ट" का लक्ष्य प्रकार क्यों है?
user1056903 19

7

डायनेमिक_कास्ट के बिना Instanceof कार्यान्वयन

मुझे लगता है कि यह सवाल आज भी प्रासंगिक है। C ++ 11 मानक का उपयोग करके अब आप इस तरह instanceofका उपयोग किए बिना एक फ़ंक्शन को लागू करने में सक्षम हैं dynamic_cast:

if (dynamic_cast<B*>(aPtr) != nullptr) {
  // aPtr is instance of B
} else {
  // aPtr is NOT instance of B
}

लेकिन आप अभी भी RTTIसमर्थन पर निर्भर हैं । तो यहाँ कुछ मैक्रोज़ और मेटाप्रोग्रामिंग मैजिक के आधार पर इस समस्या के लिए मेरा समाधान है। एकमात्र दोष यह है कि यह दृष्टिकोण काम नहीं करता है एकाधिक वंशानुक्रम के

InstanceOfMacros.h

#include <set>
#include <tuple>
#include <typeindex>

#define _EMPTY_BASE_TYPE_DECL() using BaseTypes = std::tuple<>;
#define _BASE_TYPE_DECL(Class, BaseClass) \
  using BaseTypes = decltype(std::tuple_cat(std::tuple<BaseClass>(), Class::BaseTypes()));
#define _INSTANCE_OF_DECL_BODY(Class)                                 \
  static const std::set<std::type_index> baseTypeContainer;           \
  virtual bool instanceOfHelper(const std::type_index &_tidx) {       \
    if (std::type_index(typeid(ThisType)) == _tidx) return true;      \
    if (std::tuple_size<BaseTypes>::value == 0) return false;         \
    return baseTypeContainer.find(_tidx) != baseTypeContainer.end();  \
  }                                                                   \
  template <typename... T>                                            \
  static std::set<std::type_index> getTypeIndexes(std::tuple<T...>) { \
    return std::set<std::type_index>{std::type_index(typeid(T))...};  \
  }

#define INSTANCE_OF_SUB_DECL(Class, BaseClass) \
 protected:                                    \
  using ThisType = Class;                      \
  _BASE_TYPE_DECL(Class, BaseClass)            \
  _INSTANCE_OF_DECL_BODY(Class)

#define INSTANCE_OF_BASE_DECL(Class)                                                    \
 protected:                                                                             \
  using ThisType = Class;                                                               \
  _EMPTY_BASE_TYPE_DECL()                                                               \
  _INSTANCE_OF_DECL_BODY(Class)                                                         \
 public:                                                                                \
  template <typename Of>                                                                \
  typename std::enable_if<std::is_base_of<Class, Of>::value, bool>::type instanceOf() { \
    return instanceOfHelper(std::type_index(typeid(Of)));                               \
  }

#define INSTANCE_OF_IMPL(Class) \
  const std::set<std::type_index> Class::baseTypeContainer = Class::getTypeIndexes(Class::BaseTypes());

डेमो

फिर आप इस सामग्री का उपयोग कर सकते हैं ( सावधानी के साथ हैं:

DemoClassHierarchy.hpp *

#include "InstanceOfMacros.h"

struct A {
  virtual ~A() {}
  INSTANCE_OF_BASE_DECL(A)
};
INSTANCE_OF_IMPL(A)

struct B : public A {
  virtual ~B() {}
  INSTANCE_OF_SUB_DECL(B, A)
};
INSTANCE_OF_IMPL(B)

struct C : public A {
  virtual ~C() {}
  INSTANCE_OF_SUB_DECL(C, A)
};
INSTANCE_OF_IMPL(C)

struct D : public C {
  virtual ~D() {}
  INSTANCE_OF_SUB_DECL(D, C)
};
INSTANCE_OF_IMPL(D)

निम्न कोड सही व्यवहार को अल्पविकसित करने के लिए एक छोटा डेमो प्रस्तुत करता है।

InstanceOfDemo.cpp

#include <iostream>
#include <memory>
#include "DemoClassHierarchy.hpp"

int main() {
  A *a2aPtr = new A;
  A *a2bPtr = new B;
  std::shared_ptr<A> a2cPtr(new C);
  C *c2dPtr = new D;
  std::unique_ptr<A> a2dPtr(new D);

  std::cout << "a2aPtr->instanceOf<A>(): expected=1, value=" << a2aPtr->instanceOf<A>() << std::endl;
  std::cout << "a2aPtr->instanceOf<B>(): expected=0, value=" << a2aPtr->instanceOf<B>() << std::endl;
  std::cout << "a2aPtr->instanceOf<C>(): expected=0, value=" << a2aPtr->instanceOf<C>() << std::endl;
  std::cout << "a2aPtr->instanceOf<D>(): expected=0, value=" << a2aPtr->instanceOf<D>() << std::endl;
  std::cout << std::endl;
  std::cout << "a2bPtr->instanceOf<A>(): expected=1, value=" << a2bPtr->instanceOf<A>() << std::endl;
  std::cout << "a2bPtr->instanceOf<B>(): expected=1, value=" << a2bPtr->instanceOf<B>() << std::endl;
  std::cout << "a2bPtr->instanceOf<C>(): expected=0, value=" << a2bPtr->instanceOf<C>() << std::endl;
  std::cout << "a2bPtr->instanceOf<D>(): expected=0, value=" << a2bPtr->instanceOf<D>() << std::endl;
  std::cout << std::endl;
  std::cout << "a2cPtr->instanceOf<A>(): expected=1, value=" << a2cPtr->instanceOf<A>() << std::endl;
  std::cout << "a2cPtr->instanceOf<B>(): expected=0, value=" << a2cPtr->instanceOf<B>() << std::endl;
  std::cout << "a2cPtr->instanceOf<C>(): expected=1, value=" << a2cPtr->instanceOf<C>() << std::endl;
  std::cout << "a2cPtr->instanceOf<D>(): expected=0, value=" << a2cPtr->instanceOf<D>() << std::endl;
  std::cout << std::endl;
  std::cout << "c2dPtr->instanceOf<A>(): expected=1, value=" << c2dPtr->instanceOf<A>() << std::endl;
  std::cout << "c2dPtr->instanceOf<B>(): expected=0, value=" << c2dPtr->instanceOf<B>() << std::endl;
  std::cout << "c2dPtr->instanceOf<C>(): expected=1, value=" << c2dPtr->instanceOf<C>() << std::endl;
  std::cout << "c2dPtr->instanceOf<D>(): expected=1, value=" << c2dPtr->instanceOf<D>() << std::endl;
  std::cout << std::endl;
  std::cout << "a2dPtr->instanceOf<A>(): expected=1, value=" << a2dPtr->instanceOf<A>() << std::endl;
  std::cout << "a2dPtr->instanceOf<B>(): expected=0, value=" << a2dPtr->instanceOf<B>() << std::endl;
  std::cout << "a2dPtr->instanceOf<C>(): expected=1, value=" << a2dPtr->instanceOf<C>() << std::endl;
  std::cout << "a2dPtr->instanceOf<D>(): expected=1, value=" << a2dPtr->instanceOf<D>() << std::endl;

  delete a2aPtr;
  delete a2bPtr;
  delete c2dPtr;

  return 0;
}

आउटपुट:

a2aPtr->instanceOf<A>(): expected=1, value=1
a2aPtr->instanceOf<B>(): expected=0, value=0
a2aPtr->instanceOf<C>(): expected=0, value=0
a2aPtr->instanceOf<D>(): expected=0, value=0

a2bPtr->instanceOf<A>(): expected=1, value=1
a2bPtr->instanceOf<B>(): expected=1, value=1
a2bPtr->instanceOf<C>(): expected=0, value=0
a2bPtr->instanceOf<D>(): expected=0, value=0

a2cPtr->instanceOf<A>(): expected=1, value=1
a2cPtr->instanceOf<B>(): expected=0, value=0
a2cPtr->instanceOf<C>(): expected=1, value=1
a2cPtr->instanceOf<D>(): expected=0, value=0

c2dPtr->instanceOf<A>(): expected=1, value=1
c2dPtr->instanceOf<B>(): expected=0, value=0
c2dPtr->instanceOf<C>(): expected=1, value=1
c2dPtr->instanceOf<D>(): expected=1, value=1

a2dPtr->instanceOf<A>(): expected=1, value=1
a2dPtr->instanceOf<B>(): expected=0, value=0
a2dPtr->instanceOf<C>(): expected=1, value=1
a2dPtr->instanceOf<D>(): expected=1, value=1

प्रदर्शन

सबसे दिलचस्प सवाल जो अब उठता है, अगर यह बुराई सामान के उपयोग की तुलना में अधिक कुशल है dynamic_cast । इसलिए मैंने एक बहुत ही बुनियादी प्रदर्शन माप एप्लिकेशन लिखा है।

InstanceOfPerformance.cpp

#include <chrono>
#include <iostream>
#include <string>
#include "DemoClassHierarchy.hpp"

template <typename Base, typename Derived, typename Duration>
Duration instanceOfMeasurement(unsigned _loopCycles) {
  auto start = std::chrono::high_resolution_clock::now();
  volatile bool isInstanceOf = false;
  for (unsigned i = 0; i < _loopCycles; ++i) {
    Base *ptr = new Derived;
    isInstanceOf = ptr->template instanceOf<Derived>();
    delete ptr;
  }
  auto end = std::chrono::high_resolution_clock::now();
  return std::chrono::duration_cast<Duration>(end - start);
}

template <typename Base, typename Derived, typename Duration>
Duration dynamicCastMeasurement(unsigned _loopCycles) {
  auto start = std::chrono::high_resolution_clock::now();
  volatile bool isInstanceOf = false;
  for (unsigned i = 0; i < _loopCycles; ++i) {
    Base *ptr = new Derived;
    isInstanceOf = dynamic_cast<Derived *>(ptr) != nullptr;
    delete ptr;
  }
  auto end = std::chrono::high_resolution_clock::now();
  return std::chrono::duration_cast<Duration>(end - start);
}

int main() {
  unsigned testCycles = 10000000;
  std::string unit = " us";
  using DType = std::chrono::microseconds;

  std::cout << "InstanceOf performance(A->D)  : " << instanceOfMeasurement<A, D, DType>(testCycles).count() << unit
            << std::endl;
  std::cout << "InstanceOf performance(A->C)  : " << instanceOfMeasurement<A, C, DType>(testCycles).count() << unit
            << std::endl;
  std::cout << "InstanceOf performance(A->B)  : " << instanceOfMeasurement<A, B, DType>(testCycles).count() << unit
            << std::endl;
  std::cout << "InstanceOf performance(A->A)  : " << instanceOfMeasurement<A, A, DType>(testCycles).count() << unit
            << "\n"
            << std::endl;
  std::cout << "DynamicCast performance(A->D) : " << dynamicCastMeasurement<A, D, DType>(testCycles).count() << unit
            << std::endl;
  std::cout << "DynamicCast performance(A->C) : " << dynamicCastMeasurement<A, C, DType>(testCycles).count() << unit
            << std::endl;
  std::cout << "DynamicCast performance(A->B) : " << dynamicCastMeasurement<A, B, DType>(testCycles).count() << unit
            << std::endl;
  std::cout << "DynamicCast performance(A->A) : " << dynamicCastMeasurement<A, A, DType>(testCycles).count() << unit
            << "\n"
            << std::endl;
  return 0;
}

परिणाम भिन्न होते हैं और अनिवार्य रूप से संकलक अनुकूलन की डिग्री पर आधारित होते हैं। g++ -std=c++11 -O0 -o instanceof-performance InstanceOfPerformance.cppमेरे स्थानीय मशीन पर आउटपुट का उपयोग करके प्रदर्शन माप कार्यक्रम को संकलित करना था:

InstanceOf performance(A->D)  : 699638 us
InstanceOf performance(A->C)  : 642157 us
InstanceOf performance(A->B)  : 671399 us
InstanceOf performance(A->A)  : 626193 us

DynamicCast performance(A->D) : 754937 us
DynamicCast performance(A->C) : 706766 us
DynamicCast performance(A->B) : 751353 us
DynamicCast performance(A->A) : 676853 us

मम्म, यह परिणाम बहुत ही साहसी था, क्योंकि समय दर्शाता है कि दृष्टिकोण की तुलना में नया दृष्टिकोण बहुत तेज नहीं है dynamic_cast। यह विशेष परीक्षण मामले के लिए और भी कम कुशल है जो परीक्षण करता है कि कोई सूचक Aइसका उदाहरण है Aलेकिन हमारे द्विआधारी का उपयोग कर संकलक otpimization ट्यूनिंग द्वारा ज्वार बदल जाता है। संबंधित कंपाइलर कमांड है g++ -std=c++11 -O3 -o instanceof-performance InstanceOfPerformance.cpp। मेरी स्थानीय मशीन पर परिणाम आश्चर्यजनक था:

InstanceOf performance(A->D)  : 3035 us
InstanceOf performance(A->C)  : 5030 us
InstanceOf performance(A->B)  : 5250 us
InstanceOf performance(A->A)  : 3021 us

DynamicCast performance(A->D) : 666903 us
DynamicCast performance(A->C) : 698567 us
DynamicCast performance(A->B) : 727368 us
DynamicCast performance(A->A) : 3098 us

यदि आप कई विरासतों पर भरोसा नहीं कर रहे हैं, तो अच्छे पुराने सी मैक्रोज़, आरटीटीआई और टेम्पलेट मेटाप्रोग्रामिंग के विरोधी नहीं हैं और अपनी कक्षा पदानुक्रम की कक्षाओं में कुछ छोटे निर्देशों को जोड़ने के लिए बहुत आलसी नहीं हैं, तो यह दृष्टिकोण आपके आवेदन को थोड़ा बढ़ा सकता है इसके प्रदर्शन के संबंध में, यदि आप अक्सर सूचक के उदाहरण की जांच करते हैं। लेकिन सावधानी के साथ इसका उपयोग करें । इस दृष्टिकोण की शुद्धता के लिए कोई वारंटी नहीं है।

नोट: सभी डेमो को clang (Apple LLVM version 9.0.0 (clang-900.0.39.2))मैकबुक प्रो मिड 2012 में macOS सिएरा के तहत उपयोग करके संकलित किया गया था।

संपादित करें: मैंने लिनक्स मशीन के उपयोग से प्रदर्शन का भी परीक्षण किया है gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609। इस प्लेटफ़ॉर्म पर परफ्यूम का लाभ इतना महत्वपूर्ण नहीं था जितना कि क्लैंग वाले मैकओ पर।

आउटपुट (संकलक अनुकूलन के बिना):

InstanceOf performance(A->D)  : 390768 us
InstanceOf performance(A->C)  : 333994 us
InstanceOf performance(A->B)  : 334596 us
InstanceOf performance(A->A)  : 300959 us

DynamicCast performance(A->D) : 331942 us
DynamicCast performance(A->C) : 303715 us
DynamicCast performance(A->B) : 400262 us
DynamicCast performance(A->A) : 324942 us

आउटपुट (संकलक अनुकूलन के साथ):

InstanceOf performance(A->D)  : 209501 us
InstanceOf performance(A->C)  : 208727 us
InstanceOf performance(A->B)  : 207815 us
InstanceOf performance(A->A)  : 197953 us

DynamicCast performance(A->D) : 259417 us
DynamicCast performance(A->C) : 256203 us
DynamicCast performance(A->B) : 261202 us
DynamicCast performance(A->A) : 193535 us

सुविचारित उत्तर! मुझे खुशी है कि आपने समय प्रदान किया। यह एक दिलचस्प रीड था।
एरिक

0

dynamic_castको अक्षम माना जाता है। यह वंशानुक्रम पदानुक्रम का पता लगाता है, और यह है एकमात्र समाधान है यदि आपके पास विरासत के कई स्तर हैं, और यह जांचने की आवश्यकता है कि क्या वस्तु अपने प्रकार पदानुक्रम में किसी एक प्रकार का उदाहरण है।

लेकिन अगर इसका एक अधिक सीमित रूप instanceofकेवल तभी जांचता है कि कोई वस्तु आपके द्वारा निर्दिष्ट प्रकार की है, आपकी आवश्यकताओं के लिए पर्याप्त है, तो नीचे दिया गया कार्य बहुत अधिक कुशल होगा:

template<typename T, typename K>
inline bool isType(const K &k) {
    return typeid(T).hash_code() == typeid(k).hash_code();
}

यहां एक उदाहरण दिया गया है कि आप ऊपर दिए गए फ़ंक्शन को कैसे लागू करेंगे:

DerivedA k;
Base *p = &k;

cout << boolalpha << isType<DerivedA>(*p) << endl;  // true
cout << boolalpha << isType<DerivedB>(*p) << endl;  // false

आप टेम्पलेट प्रकार निर्दिष्ट Aकरेंगे (जिस प्रकार की आप जाँच कर रहे हैं), और उस ऑब्जेक्ट में पास करें जिसे आप तर्क के रूप में परीक्षण करना चाहते हैं (जिसमें से टेम्पलेट प्रकार Kका अनुमान लगाया जाएगा)।


मानक को विभिन्न प्रकारों के लिए अद्वितीय होने के लिए हैश_कोड की आवश्यकता नहीं होती है, इसलिए यह अविश्वसनीय है।
मटनज़

2
क्या टाइपिड (T) स्वयं समानता के साथ तुलनीय नहीं है, इसलिए हैशकोड पर निर्भरता की आवश्यकता नहीं है?
पॉल स्टेलियन

-5
#include <iostream.h>
#include<typeinfo.h>

template<class T>
void fun(T a)
{
  if(typeid(T) == typeid(int))
  {
     //Do something
     cout<<"int";
  }
  else if(typeid(T) == typeid(float))
  {
     //Do Something else
     cout<<"float";
  }
}

void main()
 {
      fun(23);
      fun(90.67f);
 }

1
यह एक बहुत बुरा उदाहरण है। ओवरलोडिंग का उपयोग क्यों न करें, जो सस्ता है?
user1095108

11
मुख्य समस्या यह है कि यह प्रश्न का उत्तर देने में विफल रहता है। instanceofडायनामिक प्रकार पर प्रश्न करता है, लेकिन इस उत्तर में डायनेमिक और स्टैटिक टाइप हमेशा मेल खाते हैं।
एमएसलटर्स

@ आप किस तरह से जवाब दे रहे हैं, यह सवाल पूछा जा रहा है!
प्रोग्रामर

-11

इसने कोड का उपयोग करके मेरे लिए एकदम सही काम किया: जीसीसी के साथ ब्लॉक आईडीई

#include<iostream>
#include<typeinfo>
#include<iomanip>
#define SIZE 20
using namespace std;

class Publication
{
protected:
    char title[SIZE];
    int price;

public:
    Publication()
    {
        cout<<endl<<" Enter title of media : ";
        cin>>title;

        cout<<endl<<" Enter price of media : ";
        cin>>price;
    }

    virtual void show()=0;
};

class Book : public Publication
{
    int pages;

public:
    Book()
    {
        cout<<endl<<" Enter number of pages : ";
        cin>>pages;
    }

    void show()
    {
        cout<<endl<<setw(12)<<left<<" Book Title"<<": "<<title;
        cout<<endl<<setw(12)<<left<<" Price"<<": "<<price;
        cout<<endl<<setw(12)<<left<<" Pages"<<": "<<pages;
        cout<<endl<<" ----------------------------------------";
    }
};

class Tape : public Publication
{
    int duration;

public:
    Tape()
    {
        cout<<endl<<" Enter duration in minute : ";
        cin>>duration;
    }

    void show()
    {
        cout<<endl<<setw(10)<<left<<" Tape Title"<<": "<<title;
        cout<<endl<<setw(10)<<left<<" Price"<<": "<<price;
        cout<<endl<<setw(10)<<left<<" Duration"<<": "<<duration<<" minutes";
        cout<<endl<<" ----------------------------------------";
    }
};
int main()
{
    int n, i, type;

    cout<<endl<<" Enter number of media : ";
    cin>>n;

    Publication **p = new Publication*[n];
    cout<<endl<<" Enter "<<n<<" media details : ";

    for(i=0;i<n;i++)
    {
        cout<<endl<<" Select Media Type [ 1 - Book / 2 - Tape ] ";
        cin>>type;

        if ( type == 1 )
        {
            p[i] = new Book();
        }
        else
        if ( type == 2 )
        {
            p[i] = new Tape();
        }
        else
        {
            i--;
            cout<<endl<<" Invalid type. You have to Re-enter choice";
        }
    }

    for(i=0;i<n;i++)
    {
        if ( typeid(Book) == typeid(*p[i]) )
        {
            p[i]->show();
        }
    }

    return 0;
}

1
@programmer मुझे लगता है कि आपको @pgp पर कॉल करने का मतलब है, मैंने बस उसका कोड फॉर्मेटिंग तय किया है। इसके अलावा, उसका जवाब मूल रूप से "उपयोग typeid" लगता है , जो गलत है ("कोई गारंटी नहीं है कि एक ही एसटी :: type_info उदाहरण एक ही प्रकार पर टाइपिड अभिव्यक्ति के सभी मूल्यांकन द्वारा संदर्भित किया जाएगा ... assert(typeid(A) == typeid(A)); /* not guaranteed */", देखें cppreference.com ), यह इंगित करता है कि उसने कम से कम सवाल का जवाब देने की कोशिश की, यदि अनपेक्षित रूप से क्योंकि उसने न्यूनतम काम करने का उदाहरण पेश करने की उपेक्षा की।
एंड्रेस रिओप्रियो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.