दिलचस्प पोस्ट
इंटेल HD 3000 पर उचित ओपनजीएल आरंभीकरण क्या है? वसंत MVC 415 असमर्थित मीडिया प्रकार छवि को एक मेज पर लोड करें I लिंक्ड सूची विभाजन समारोह और उलट परिणाम सीएसएस आईपैड / आईफोन पर अजीब रेंडरिंग बटन सबमिट करें Javax.preistence.Query.getResultList () रिटर्न रिक्त हो सकता है? मैं एरेज़ को & a = & b के रूप में क्यों नहीं दे सकता? कैसे uninitialized निरंतर रेक को ठीक करने के लिए :: Heroku पर डीएसएल समस्या? साधारण एचटीएमएल डीएम: तत्व कैसे निकालें? ऐप अस्वीकार किया गया, लेकिन मैं यूडीआईडी ​​का उपयोग नहीं करता Scanf के सी # समकक्ष के लिए खोज रहे हैं एकाधिक गैर-ब्रेकिंग रिक्त स्थान ("nbsp") के बजाय टैब स्थान? टेक्स्ट चौड़ाई की गणना करना पोस्ट पर खाली रिक कोड में UIButton के लिए एक छवि सेट करना

dynamic_cast और static_cast सी ++ में

मैं सी ++ में dynamic_cast कीवर्ड के साथ काफी उलझन में हूँ

 struct A { virtual void f() { } }; struct B : public A { }; struct C { }; void f () { A a; B b; A* ap = &b; B* b1 = dynamic_cast<B*> (&a); // NULL, because 'a' is not a 'B' B* b2 = dynamic_cast<B*> (ap); // 'b' C* c = dynamic_cast<C*> (ap); // NULL. A& ar = dynamic_cast<A&> (*ap); // Ok. B& br = dynamic_cast<B&> (*ap); // Ok. C& cr = dynamic_cast<C&> (*ap); // std::bad_cast } 

परिभाषा कहती है:

dynamic_cast कीवर्ड एक सूचक या संदर्भ प्रकार से दूसरे को एक डाट करता है, रनटाइम चेक करने के लिए कलाकारों की वैधता सुनिश्चित करने के लिए

क्या हम सी में सी ++ के dynamic_cast के बराबर लिख सकते हैं ताकि मैं चीजों को बेहतर समझ सकूं?

Solutions Collecting From Web of "dynamic_cast और static_cast सी ++ में"

यहां static_cast<> और dynamic_cast<> पर एक static_cast<> क्योंकि वे पॉइंटर्स से संबंधित हैं। यह सिर्फ 101-स्तर का ठहरनेवाला है, इसमें सभी जटिलताओं को शामिल नहीं किया गया है।

static_cast <Type *> (ptr)

यह ptr में ptr लेता है और इसे सुरक्षित रूप से प्रकार के एक संकेतक के रूप में ptr Type* यह कलाकार संकलन समय पर किया जाता है। यदि प्रकार प्रकार संबंधित हैं तो यह केवल कलाकारों को ही प्रदर्शन करेगा यदि प्रकार से संबंधित नहीं हैं, तो आपको एक कंपाइलर त्रुटि मिलेगी। उदाहरण के लिए:

 class B {}; class D : public B {}; class X {}; int main() { D* d = new D; B* b = static_cast<B*>(d); // this works X* x = static_cast<X*>(d); // ERROR - Won't compile return 0; } 

गतिशील_कास्ट <प्रकार *> (पीटीआर)

यह फिर से ptr में पॉइंटर लेने का प्रयास करता है और सुरक्षित रूप से इसे प्रकार का एक सूचक Type* । लेकिन यह कलाकार क्रमशः पर निष्पादित होता है, समय संकलित नहीं करता है क्योंकि यह एक रन-टाइम कास्ट है, क्योंकि यह विशेष रूप से उपयोगी है जब बहुरूपक वर्गों के साथ मिलाया जाता है। वास्तव में, निश्चित मामलों में, कलाकारों को कानूनी होने के लिए कक्षाओं को बहुरूपृत होना चाहिए।

कस्टर्स दो दिशाओं में से एक में जा सकते हैं: आधार से व्युत्पन्न (बी 2 डी) या व्युत्पन्न टू बेस (डी 2 बी) यह काफी सरल है कि यह देखने के लिए कि कैसे डी 2 बी कैस्ट रनटाइम पर काम करेगा। या तो ptr Type से व्युत्पन्न था या नहीं था। डी 2 बी गतिशील_कास्ट <> एस के मामले में, नियम सरल होते हैं। आप कुछ भी करने के लिए कुछ भी डालने की कोशिश कर सकते हैं, और अगर ptr वास्तव में Type से प्राप्त हुआ था, तो आप dynamic_cast से एक Type* पॉइंटर वापस dynamic_cast । अन्यथा, आपको एक शून्य सूचक मिलेगा

लेकिन बी 2 डी डाले गए हैं थोड़ा और अधिक जटिल। निम्नलिखित कोड पर विचार करें:

 #include <iostream> using namespace std; class Base { public: virtual void DoIt() = 0; // pure virtual virtual ~Base() {}; }; class Foo : public Base { public: virtual void DoIt() { cout << "Foo"; }; void FooIt() { cout << "Fooing It..."; } }; class Bar : public Base { public : virtual void DoIt() { cout << "Bar"; } void BarIt() { cout << "baring It..."; } }; Base* CreateRandom() { if( (rand()%2) == 0 ) return new Foo; else return new Bar; } int main() { for( int n = 0; n < 10; ++n ) { Base* base = CreateRandom(); base->DoIt(); Bar* bar = (Bar*)base; bar->BarIt(); } return 0; } 

main() यह नहीं बता सकता कि किस प्रकार का ऑब्जेक्ट CreateRandom() वापस आएगा, इसलिए सी-स्टाइल कास्ट Bar* bar = (Bar*)base; निश्चित रूप से टाइप-सुरक्षित नहीं है आप इसे कैसे तय कर सकते हैं? एक तरह से एक समारोह जोड़ने के लिए होगा जैसे bool AreYouABar() const = 0; बेस क्लास के लिए और Bar और Foo से false से true वापसी। लेकिन एक और तरीका है: dynamic_cast<> उपयोग करें dynamic_cast<> :

 int main() { for( int n = 0; n < 10; ++n ) { Base* base = CreateRandom(); base->DoIt(); Bar* bar = dynamic_cast<Bar*>(base); Foo* foo = dynamic_cast<Foo*>(base); if( bar ) bar->BarIt(); if( foo ) foo->FooIt(); } return 0; } 

रनटाइम पर निष्पादित कारागार, और ऑब्जेक्ट की पूछताछ करते हुए काम करते हैं (यह कैसे की चिंता करने की कोई जरूरत नहीं है), यह पूछने पर कि क्या वह प्रकार हम खोज रहे हैं। यदि यह है, तो dynamic_cast<Type*> एक सूचक देता है; अन्यथा यह शून्य प्राप्त करता है

dynamic_cast<> , dynamic_cast<> , फ़ू और बार का उपयोग करने के लिए इस बेस-टू- dynamic_cast<> किए गए कास्टिंग के लिए मानक कॉल पॉलिमोरफिक प्रकारों को क्या करना चाहिए। एक बहुरूपिक प्रकार के होने के लिए, आपकी कक्षा में कम से कम एक virtual फ़ंक्शन होना चाहिए। यदि आपकी कक्षाएं बहुरूपक प्रकार नहीं हैं, तो dynamic_cast का आधार-से-व्युत्पन्न उपयोग संकलन नहीं करेगा। उदाहरण:

 class Base {}; class Der : public Base {}; int main() { Base* base = new Der; Der* der = dynamic_cast<Der*>(base); // ERROR - Won't compile return 0; } 

आधार के लिए एक आभासी फ़ंक्शन को जोड़ना, जैसे कि वर्चुअल डॉट, दोनों बेस और डेर बहुरूपता प्रकार बनाती हैं:

 class Base { public: virtual ~Base(){}; }; class Der : public Base {}; int main() { Base* base = new Der; Der* der = dynamic_cast<Der*>(base); // OK return 0; } 

जब तक आप अपना स्वयं का हाथ-रोल किए गए RTTI (और सिस्टम को बायपास करते हुए) लागू कर रहे हैं, तो सी ++ उपयोगकर्ता-स्तर कोड में dynamic_cast सीधे लागू करना संभव नहीं है dynamic_cast बहुत सी ++ कार्यान्वयन की आरटीटीआई प्रणाली में बंधी है

लेकिन, आपको आरटीटीआई (और इस तरह dynamic_cast ) को समझने में मदद करने के लिए, आपको <typeinfo> हैडर और typeid ऑपरेटर पर पढ़ना चाहिए। यह आपके पास मौजूद ऑब्जेक्ट के अनुरूप प्रकार की जानकारी देता है, और आप इन प्रकार की जानकारी ऑब्जेक्ट्स से विभिन्न (सीमित) चीजों की पूछताछ कर सकते हैं।

सी में कोड से अधिक, मुझे लगता है कि एक अंग्रेजी परिभाषा पर्याप्त हो सकती है:

एक वर्ग को देखते हुए, जिसमें एक व्युत्पन्न श्रेणी प्राप्त हुई है, dynamic_cast एक dynamic_cast पॉइंटर को एक व्युत्पन्न सूचक में बदल देगा, यदि और केवल वास्तविक ऑब्जेक्ट पर इंगित किया जाए तो वास्तव में एक व्युत्पन्न वस्तु है।

 class Base { virtual ~Base() {} }; class Derived : public Base {}; class Derived2 : public Base {}; class ReDerived : public Derived {}; void test( Base & base ) { dynamic_cast<Derived&>(base); } int main() { Base b; Derived d; Derived2 d2; ReDerived rd; test( b ); // throw: b is not a Derived object test( d ); // ok test( d2 ); // throw: d2 is not a Derived object test( rd ); // ok: rd is a ReDerived, and thus a derived object } 

उदाहरण के लिए, test लिए कॉल Base संदर्भ में विभिन्न वस्तुओं को बांधता है। आंतरिक रूप से एक प्रकार के तरीके में Derived होने के संदर्भ में डाउनकास्ट किया जाता है: उदासीन उन मामलों के लिए सफल होगा जहां संदर्भित वस्तु वास्तव में व्युत्पत्ति का एक उदाहरण है।

एक dynamic_cast RTTI का उपयोग करके एक प्रकार की जांच करता है यदि यह असफल हो जाता है तो यह आपको एक अपवाद (यदि आप इसे एक संदर्भ दिया) या शून्य अगर आप इसे एक संकेतक दे देंगे

निम्न प्रकार की जाँच के मामले में सी ++ के dynamic_cast से जो कुछ मिलता है, वह वास्तव में करीब नहीं है, लेकिन हो सकता है कि यह आपको इसके उद्देश्य को थोड़ा बेहतर समझने में मदद करे:

 struct Animal // Would be a base class in C++ { enum Type { Dog, Cat }; Type type; }; Animal * make_dog() { Animal * dog = new Animal; dog->type = Animal::Dog; return dog; } Animal * make_cat() { Animal * cat = new Animal; cat->type = Animal::Cat; return cat; } Animal * dyn_cast(AnimalType type, Animal * animal) { if(animal->type == type) return animal; return 0; } void bark(Animal * dog) { assert(dog->type == Animal::Dog); // make "dog" bark } int main() { Animal * animal; if(rand() % 2) animal = make_dog(); else animal = make_cat(); // At this point we have no idea what kind of animal we have // so we use dyn_cast to see if it's a dog if(dyn_cast(Animal::Dog, animal)) { bark(animal); // we are sure the call is safe } delete animal; } 

सी में कोई कक्षाएं नहीं हैं, इसलिए उस भाषा में गतिशील_कास्ट लिखना असंभव है सी संरचनाओं के पास तरीकों (परिणामस्वरूप, उनके पास आभासी विधियां नहीं हैं) नहीं हैं, इसलिए इसमें "गतिशील" कुछ भी नहीं है

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

संपादित करें

यहां एक कार्यान्वयन है जो एक तकनीक को दर्शाता है। मैं दावा नहीं कर रहा हूं कि कंपाइलर इस तरह से कुछ भी उपयोग करता है, लेकिन मुझे लगता है कि यह अवधारणाओं को दर्शाता है:

 class SafeCastableBase { public: typedef long TypeID; static TypeID s_nextTypeID; static TypeID GetNextTypeID() { return s_nextTypeID++; } static TypeID GetTypeID() { return 0; } virtual bool CanCastTo(TypeID id) { if (GetTypeID() != id) { return false; } return true; } template <class Target> static Target *SafeCast(SafeCastableBase *pSource) { if (pSource->CanCastTo(Target::GetTypeID())) { return (Target*)pSource; } return NULL; } }; SafeCastableBase::TypeID SafeCastableBase::s_nextTypeID = 1; class TypeIDInitializer { public: TypeIDInitializer(SafeCastableBase::TypeID *pTypeID) { *pTypeID = SafeCastableBase::GetNextTypeID(); } }; class ChildCastable : public SafeCastableBase { public: static TypeID s_typeID; static TypeID GetTypeID() { return s_typeID; } virtual bool CanCastTo(TypeID id) { if (GetTypeID() != id) { return SafeCastableBase::CanCastTo(id); } return true; } }; SafeCastableBase::TypeID ChildCastable::s_typeID; TypeIDInitializer ChildCastableInitializer(&ChildCastable::s_typeID); class PeerChildCastable : public SafeCastableBase { public: static TypeID s_typeID; static TypeID GetTypeID() { return s_typeID; } virtual bool CanCastTo(TypeID id) { if (GetTypeID() != id) { return SafeCastableBase::CanCastTo(id); } return true; } }; SafeCastableBase::TypeID PeerChildCastable::s_typeID; TypeIDInitializer PeerChildCastableInitializer(&PeerChildCastable::s_typeID); int _tmain(int argc, _TCHAR* argv[]) { ChildCastable *pChild = new ChildCastable(); SafeCastableBase *pBase = new SafeCastableBase(); PeerChildCastable *pPeerChild = new PeerChildCastable(); ChildCastable *pSameChild = SafeCastableBase::SafeCast<ChildCastable>(pChild); SafeCastableBase *pBaseToChild = SafeCastableBase::SafeCast<SafeCastableBase>(pChild); ChildCastable *pNullDownCast = SafeCastableBase::SafeCast<ChildCastable>(pBase); SafeCastableBase *pBaseToPeerChild = SafeCastableBase::SafeCast<SafeCastableBase>(pPeerChild); ChildCastable *pNullCrossCast = SafeCastableBase::SafeCast<ChildCastable>(pPeerChild); return 0; } 

dynamic_cast RTTI का उपयोग करता है यह आपके आवेदन को धीमा कर सकता है, आप RTTI के बिना डाउनकास्टिंग प्राप्त करने के लिए विज़िटर डिजाइन पैटर्न के संशोधन का उपयोग कर सकते हैं http://arturx64.github.io/programming-world/2016/02/06/lazy-visitor.html

static_cast< Type* >(ptr)

C ++ में static_cast परिदृश्यों में उपयोग किया जा सकता है जहां सभी प्रकार का कास्टिंग समय संकलन में सत्यापित किया जा सकता है

dynamic_cast< Type* >(ptr)

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

जैसे 1:

 #include <iostream> using namespace std; class A { public: virtual void f(){cout << "A::f()" << endl;} }; class B : public A { public: void f(){cout << "B::f()" << endl;} }; int main() { A a; B b; af(); // A::f() bf(); // B::f() A *pA = &a; B *pB = &b; pA->f(); // A::f() pB->f(); // B::f() pA = &b; // pB = &a; // not allowed pB = dynamic_cast<B*>(&a); // allowed but it returns NULL return 0; } 

अधिक जानकारी के लिए यहां क्लिक करें

जैसे 2:

 #include <iostream> using namespace std; class A { public: virtual void print()const {cout << " A\n";} }; class B { public: virtual void print()const {cout << " B\n";} }; class C: public A, public B { public: void print()const {cout << " C\n";} }; int main() { A* a = new A; B* b = new B; C* c = new C; a -> print(); b -> print(); c -> print(); b = dynamic_cast< B*>(a); //fails if (b) b -> print(); else cout << "no B\n"; a = c; a -> print(); //C prints b = dynamic_cast< B*>(a); //succeeds if (b) b -> print(); else cout << "no B\n"; }