c++ - pure - कन्स्ट्रक्टर से सी++ वर्चुअल फ़ंक्शन




virtual function in c++ in hindi (5)

इस प्रश्न का उत्तर यहां दिया गया है:

निम्न उदाहरण क्यों "0" प्रिंट करता है और मुझे उम्मीद है कि "1" प्रिंट करने के लिए इसके लिए क्या परिवर्तन करना चाहिए?

#include <iostream>
struct base {
   virtual const int value() const {
      return 0;
   }
   base() {
      std::cout << value() << std::endl;
   }
   virtual ~base() {}
};

struct derived : public base {
   virtual const int value() const {
      return 1;
   }
};

int main(void) {
   derived example;
}

आपको कन्स्ट्रक्टर से आभासी तरीकों को polymorphically कॉल नहीं करना चाहिए। इसके बजाय आप ऑब्जेक्ट के निर्माण के बाद उन्हें कॉल कर सकते हैं।

आपका कोड निम्नानुसार लिखा जा सकता है

struct base {
   virtual const int value() const {
      return 0;
   }
   base() {
      /* std::cout << value() << std::endl; */
   }
   virtual ~base() {}
};

struct derived : public base {
   virtual const int value() const {
      return 1;
   }
};

int main(void) {
   derived example;
   std::cout << example.value() << std::endl;
}

क्योंकि base पहले बनाया गया है और अभी तक derived में "परिपक्व" नहीं derived है। यह किसी ऑब्जेक्ट पर विधियों को कॉल नहीं कर सकता है जब यह गारंटी नहीं दे सकता कि ऑब्जेक्ट पहले ही ठीक से प्रारंभ हो चुका है।


दरअसल, इस व्यवहार को पाने का एक तरीका है। "सॉफ्टवेयर में हर समस्या को संकेत के स्तर के साथ हल किया जा सकता है।"

/* Disclaimer: I haven't done C++ in many months now, there might be a few syntax errors here and there. */
class parent
{
public:
     parent( ) { /* nothing interesting here. */ };
protected:
     struct parent_virtual
     {
         virtual void do_something( ) { cout << "in parent."; }
     };

     parent( const parent_virtual& obj )
     {
          obj.do_something( );
     }
};

class child : public parent
{
protected:
     struct child_virtual : public parent_virtual
     {
         void do_something( ) { cout << "in child."; }
     };
public:
      child( ) : parent( child_virtual( ) ) { }
};

यह कैसे काम करता है सवाल यह एक एफएक्यू आइटम है

संक्षेप में, जबकि कक्षा T का निर्माण किया जा रहा है, गतिशील प्रकार T , जो वर्चुअल कॉल को क्लास फ़ंक्शन कार्यान्वयन से व्युत्पन्न करता है, जो प्रासंगिक क्लास इनवेरिएंट स्थापित होने से पहले कोड निष्पादित कर सकता है (जावा और सी # में एक आम समस्या है, लेकिन सी ++ इस संबंध में सुरक्षित है)।

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

स्थिर या गतिशील बहुरूपता का उपयोग करके संक्षेप में, बेस क्लास कन्स्ट्रक्टर (या कक्षा) तक प्रासंगिक फ़ंक्शन कार्यान्वयन पास हो सकता है।

ऐसा करने का एक विशेष तरीका "पार्ट्स फैक्ट्री" ऑब्जेक्ट को पास करना है, जहां यह तर्क डिफॉल्ट किया जा सकता है। उदाहरण के लिए, एक सामान्य Button क्लास एक बटन निर्माण एपीआई फ़ंक्शन को अपने Widget बेस क्लास कन्स्ट्रक्टर तक पास कर सकता है, ताकि वह कन्स्ट्रक्टर सही API स्तर ऑब्जेक्ट बना सके।


सी ++ में, आप एक कन्स्ट्रक्टर से वर्चुअल / ओवर्रिडेन विधि को कॉल नहीं कर सकते हैं।

अब, एक अच्छा कारण है कि आप यह कर सकते हैं। "सॉफ़्टवेयर में सर्वोत्तम अभ्यास" के रूप में, आपको अपने कन्स्ट्रक्टर से अतिरिक्त तरीकों को कॉल करने से बचाना चाहिए, यहां तक ​​कि गैर वर्चुअल भी संभव है।

लेकिन, नियम के लिए हमेशा अपवाद होता है, इसलिए आप उन्हें अनुकरण करने के लिए "छद्म कन्स्ट्रक्टर विधि" का उपयोग करना चाह सकते हैं:

#include <iostream>

class base {
   // <constructor>
   base() {
      // do nothing in purpouse
   }
   // </constructor>

   // <destructor>
   ~base() {
      // do nothing in purpouse
   }
   // </destructor>

   // <fake-constructor>
   public virtual void create() {
      // move code from static constructor to fake constructor
      std::cout << value() << std::endl;
   }
   // </fake-constructor>

   // <fake-destructor>
   public virtual void destroy() {
      // move code from static destructor to fake destructor
      // ...
   }
   // </fake-destructor>

   public virtual const int value() const {
      return 0;
   }

   public virtual void DoSomething() {
      // std:cout << "Hello World";
   }
};

class derived : public base {
   // <fake-constructor>
   public override void create() {
      // move code from static constructor to fake constructor
      std::cout << "Im pretending to be a virtual constructor," << std::endl;
      std::cout << "and can call virtual methods" << std::endl;
   }
   // </fake-constructor>


   // <fake-destructor>
   public override void destroy() {
      // move code from static destructor to fake destructor
      std::cout << "Im pretending to be a virtual destructor," << std::endl;
      std::cout << "and can call virtual methods" << std::endl;
   }
   // </fake-destructor>

   public virtual const int value() const {
      return 1;
   }
};

int main(void) {
   // call fake virtual constructor in same line, after real constructor
   derived* example = new example(); example->create();

   // do several stuff with your objects
   example->doSomething();

   // call fake virtual destructor in same line, before real destructor
   example->destroy(); delete example();
}

एक प्लस के रूप में, मैं प्रोग्रामर को केवल फ़ील्ड संरचनाओं के लिए "संरचना" का उपयोग करने और फ़ील्ड, विधियों, रचनाकारों के साथ संरचनाओं के लिए "कक्षा" का उपयोग करने की सलाह देता हूं ...





virtual