वर्चुअल फंक्शन: Difference between revisions

From Vigyanwiki
No edit summary
Line 20: Line 20:
[[Image:ClassDiagram for VirtualFunction.png|400px|thumb|right|जानवरों का वर्ग आरेख]]उदाहरण के लिए, एक आधार वर्ग <code>Animal</code> वर्चुअल फ़ंक्शन हो सकता है <code>Eat</code>. उपवर्ग <code>Llama</code> लागू करेगा <code>Eat</code> उपवर्ग से अलग <code>Wolf</code>, लेकिन कोई आह्वान कर सकता है <code>Eat</code> पशु के रूप में संदर्भित किसी भी वर्ग के उदाहरण पर, और प्राप्त करें <code>Eat</code> विशिष्ट उपवर्ग का व्यवहार।
[[Image:ClassDiagram for VirtualFunction.png|400px|thumb|right|जानवरों का वर्ग आरेख]]उदाहरण के लिए, एक आधार वर्ग <code>Animal</code> वर्चुअल फ़ंक्शन हो सकता है <code>Eat</code>. उपवर्ग <code>Llama</code> लागू करेगा <code>Eat</code> उपवर्ग से अलग <code>Wolf</code>, लेकिन कोई आह्वान कर सकता है <code>Eat</code> पशु के रूप में संदर्भित किसी भी वर्ग के उदाहरण पर, और प्राप्त करें <code>Eat</code> विशिष्ट उपवर्ग का व्यवहार।


<वाक्यविन्यास लैंग = सीपीपी>
<syntaxhighlight lang="cpp">
वर्ग पशु {
class Animal {
  जनता:
  public:
   // जानबूझकर आभासी नहीं:
   // Intentionally not virtual:
   शून्य चाल () {
   void Move() {
  std::cout << यह जानवर किसी तरह चलता है << std::endl;
    std::cout << "This animal moves in some way" << std::endl;
   }
   }
   आभासी शून्य खाओ () = 0;
   virtual void Eat() = 0;
};
};


// क्लास एनिमल के पास इच्छा होने पर खाने की परिभाषा हो सकती है।
// The class "Animal" may possess a definition for Eat if desired.
वर्ग लामा : सार्वजनिक पशु {
class Llama : public Animal {
  जनता:
  public:
   // नॉन वर्चुअल फंक्शन मूव विरासत में मिला है लेकिन ओवरराइड नहीं हुआ है।
   // The non virtual function Move is inherited but not overridden.
   शून्य खाओ () ओवरराइड {
   void Eat() override {
  std::cout << लामा घास खाते हैं! << एसटीडी�:: एंडल;
    std::cout << "Llamas eat grass!" << std::endl;
   }
   }
};
};
</वाक्यविन्यास हाइलाइट>
</syntaxhighlight>


यह एक प्रोग्रामर को क्लास के ऑब्जेक्ट्स की सूची को प्रोसेस करने की अनुमति देता है <code>Animal</code>प्रत्येक को बारी-बारी से खाने के लिए कहना (कॉल करके)। <code>Eat</code>), यह जानने की आवश्यकता के बिना कि सूची में किस प्रकार का जानवर हो सकता है, प्रत्येक जानवर कैसे खाता है, या संभावित प्रकार के जानवरों का पूरा सेट क्या हो सकता है।
यह एक प्रोग्रामर को क्लास के ऑब्जेक्ट्स की सूची को प्रोसेस करने की अनुमति देता है <code>Animal</code>प्रत्येक को बारी-बारी से खाने के लिए कहना (कॉल करके)। <code>Eat</code>), यह जानने की आवश्यकता के बिना कि सूची में किस प्रकार का जानवर हो सकता है, प्रत्येक जानवर कैसे खाता है, या संभावित प्रकार के जानवरों का पूरा सेट क्या हो सकता है।


सी में, आभासी कार्यों के पीछे का तंत्र निम्नलिखित तरीके से प्रदान किया जा सकता है:
सी में, आभासी कार्यों के पीछे का तंत्र निम्नलिखित तरीके से प्रदान किया जा सकता है:
<वाक्यविन्यास प्रकाश लैंग = सी>
<syntaxhighlight lang="c">
#शामिल <stdio.h>
#include <stdio.h>


/* वस्तु अपनी कक्षा की ओर इशारा करती है... */
/* an object points to its class... */
संरचना पशु {
struct Animal {
  कास्ट स्ट्रक्चर एनिमलक्लास * क्लास;
    const struct AnimalClass * class;
};
};


/* जिसमें वर्चुअल फंक्शन एनिमल.ईट होता है */
/* which contains the virtual function Animal.Eat */
संरचना पशु वर्ग {
struct AnimalClass {
  शून्य (* खाओ) (संरचना पशु *); // 'वर्चुअल' फंक्शन
    void (*Eat)(struct Animal *); // 'virtual' function
};
};


/* चूँकि Animal.Move एक वर्चुअल फंक्शन नहीं है
/* Since Animal.Move is not a virtual function
  यह ऊपर की संरचना में नहीं है। */
  it is not in the structure above. */
शून्य मूव (स्ट्रक्चर एनिमल * सेल्फ)
void Move(struct Animal * self)
{
{
  प्रिंटफ ( <%p पर पशु> किसी तरह से स्थानांतरित \n, (शून्य *) स्वयं);
    printf("<Animal at %p> moved in some way\n", (void *) self);
}
}


/* मूव के विपरीत, जो एनिमल को निष्पादित करता है। सीधे मूव करें,
/* unlike Move, which executes Animal.Move directly,
  खाओ संकलन समय पर कॉल करने के लिए कौन सा फ़ंक्शन (यदि कोई हो) नहीं जान सकता है।
  Eat cannot know which function (if any) to call at compile time.
  एनिमल.ईट को केवल रन टाइम पर हल किया जा सकता है जब ईट को कॉल किया जाता है। */
  Animal.Eat can only be resolved at run time when Eat is called. */
शून्य खाओ (संरचना पशु * स्वयं)
void Eat(struct Animal * self)
{
{
  कास्ट स्ट्रक्चर एनिमलक्लास * क्लास = * (कास्ट शून्य **) स्वयं;
    const struct AnimalClass * class = *(const void **) self;
  अगर (वर्ग-> खाओ)
    if (class->Eat)  
  वर्ग-> खाओ (स्वयं); // एनिमल को निष्पादित करें। खाओ
        class->Eat(self); // execute Animal.Eat
  अन्य
    else
  fprintf(stderr, ईट नॉट इम्प्लीमेंटेड\n);
        fprintf(stderr, "Eat not implemented\n");
}
}


/* लामा का कार्यान्वयन। यह लक्ष्य कार्य है
/* implementation of Llama.Eat this is the target function
  'शून्य खाओ (संरचना पशु *)' द्वारा बुलाया जाना। */
  to be called by 'void Eat(struct Animal *).' */
स्थैतिक शून्य _लामा_ईट (संरचना पशु * स्वयं)
static void _Llama_eat(struct Animal * self)
{
{
  प्रिंटफ (<लामा %p पर> लामा घास खाते हैं!\n, (शून्य *) स्वयं);
    printf("<Llama at %p> Llama's eat grass!\n", (void *) self);  
}
}


/* क्लास इनिशियलाइज़ करें */
/* initialize class */
कास्ट स्ट्रक्चर एनिमलक्लास एनिमल = {(शून्य *) 0}; // बेस क्लास एनिमल.ईट को लागू नहीं करता है
const struct AnimalClass Animal = {(void *) 0}; // base class does not implement Animal.Eat
const स्ट्रक्चर एनिमलक्लास लामा = {_Llama_eat}; // लेकिन व्युत्पन्न वर्ग करता है
const struct AnimalClass Llama = {_Llama_eat}; // but the derived class does


पूर्णांक मुख्य (शून्य)
int main(void)
{
{
  / * अपनी कक्षा के उदाहरण के रूप में init ऑब्जेक्ट * /
  /* init objects as instance of its class */
  संरचना पशु पशु = {& पशु};
  struct Animal animal = {& Animal};
  संरचना पशु लामा = {& लामा};
  struct Animal llama = {& Llama};
  हटो (और जानवर); // पशु। हटो
  Move(& animal); // Animal.Move
  हटो (और लामा); // लामा। हटो
  Move(& llama); // Llama.Move
  खाओ (और जानवर); // एनिमल को हल नहीं कर सकता। इसलिए प्रिंट करें, इसे लागू नहीं किया गया
  Eat(& animal); // cannot resolve Animal.Eat so print "Not Implemented" to stderr
  खाओ (और लामा); // लामा को हल करता है। खाओ और निष्पादित करो
  Eat(& llama);   // resolves Llama.Eat and executes
}
}
</वाक्यविन्यास हाइलाइट>
</syntaxhighlight>
 
[[Category:All articles with unsourced statements|Virtual Function]]
[[Category:Articles with invalid date parameter in template|Virtual Function]]
[[Category:Articles with unsourced statements from October 2021|Virtual Function]]
[[Category:C++ कोड के उदाहरण वाले लेख|Virtual Function]]
[[Category:Created On 16/02/2023|Virtual Function]]
[[Category:Machine Translated Page|Virtual Function]]
[[Category:Pages with script errors|Virtual Function]]
[[Category:Short description with empty Wikidata description|Virtual Function]]
[[Category:Template documentation pages|Short description/doc]]
[[Category:Templates Vigyan Ready|Virtual Function]]


== [[सार वर्ग]] और शुद्ध आभासी कार्य ==
== [[सार वर्ग]] और शुद्ध आभासी कार्य ==

Revision as of 11:09, 18 February 2023

ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग में, सी ++ और वस्तु पास्कल जैसी भाषाओं में, वर्चुअल फ़ंक्शन या वर्चुअल विधि एक अंतर्निहित और विधि ओवरराइडिंग (प्रोग्रामिंग) फ़ंक्शन (कंप्यूटर विज्ञान) या विधि (कंप्यूटर विज्ञान) है जिसके लिए गतिशील प्रेषण की सुविधा है। यह अवधारणा ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग (OOP) के (रनटाइम) बहुरूपता (कंप्यूटर विज्ञान) भाग का एक महत्वपूर्ण हिस्सा है। संक्षेप में, एक वर्चुअल फ़ंक्शन निष्पादित किए जाने वाले लक्ष्य फ़ंक्शन को परिभाषित करता है, लेकिन लक्ष्य संकलन समय पर ज्ञात नहीं हो सकता है।

अधिकांश प्रोग्रामिंग लैंग्वेज, जैसे कि जावास्क्रिप्ट, पीएचपी और पायथन (प्रोग्रामिंग लैंग्वेज), डिफ़ॉल्ट रूप से सभी तरीकों को वर्चुअल मानते हैं[1][2] और इस व्यवहार को बदलने के लिए संशोधक प्रदान न करें। हालाँकि, कुछ भाषाएँ संशोधक प्रदान करती हैं ताकि विधियों को व्युत्पन्न कक्षाओं द्वारा ओवरराइड होने से रोका जा सके (जैसे कि जावा में अंतिम कीवर्ड (प्रोग्रामिंग भाषा)[3] और पीएचपी[4]).

उद्देश्य

वर्चुअल फ़ंक्शन की अवधारणा निम्न समस्या हल करती है:

ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग में, जब एक व्युत्पन्न वर्ग बेस क्लास से विरासत में मिलता है, तो व्युत्पन्न वर्ग का एक ऑब्जेक्ट व्युत्पन्न वर्ग प्रकार के बजाय बेस क्लास प्रकार के पॉइंटर (कंप्यूटर प्रोग्रामिंग) या संदर्भ (कंप्यूटर विज्ञान) के माध्यम से संदर्भित किया जा सकता है। . यदि व्युत्पन्न वर्ग द्वारा ओवरराइड किए गए आधार वर्ग के तरीके हैं, तो वास्तव में इस तरह के संदर्भ या सूचक द्वारा बुलाए गए तरीके को सूचक या संदर्भ के घोषित प्रकार के अनुसार, 'प्रारंभिक' (संकलक द्वारा) बाध्य (लिंक) किया जा सकता है, या 'लेट' (अर्थात् भाषा के रनटाइम सिस्टम द्वारा), वस्तु के वास्तविक प्रकार के अनुसार संदर्भित किया जाता है।

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

वर्चुअल फ़ंक्शंस प्रोग्राम को उन विधियों को कॉल करने की अनुमति देते हैं जो कोड संकलित होने के समय जरूरी नहीं हैं।[citation needed] C++ में, आभासी विधियों को जोड़कर घोषित किया जाता है virtual बेस क्लास में फ़ंक्शन की घोषणा के लिए कीवर्ड। यह संशोधक व्युत्पन्न कक्षाओं में उस पद्धति के सभी कार्यान्वयनों द्वारा विरासत में मिला है, जिसका अर्थ है कि वे एक-दूसरे को ओवर-राइड करना जारी रख सकते हैं और लेट-बाउंड हो सकते हैं। और यहां तक ​​​​कि अगर बेस क्लास के स्वामित्व वाली विधियां वर्चुअल विधि को कॉल करती हैं, तो वे इसके बजाय व्युत्पन्न विधि को कॉल करेंगे। ओवरलोडिंग तब होती है जब एक वर्ग में दो या दो से अधिक विधियों का एक ही विधि नाम होता है लेकिन अलग-अलग पैरामीटर होते हैं। ओवरराइडिंग का अर्थ है एक ही विधि नाम और मापदंडों के साथ दो विधियाँ होना। ओवरलोडिंग को फंक्शन मैचिंग और ओवरराइडिंग को डायनामिक फंक्शन मैपिंग भी कहा जाता है।

उदाहरण

सी ++

जानवरों का वर्ग आरेख

उदाहरण के लिए, एक आधार वर्ग Animal वर्चुअल फ़ंक्शन हो सकता है Eat. उपवर्ग Llama लागू करेगा Eat उपवर्ग से अलग Wolf, लेकिन कोई आह्वान कर सकता है Eat पशु के रूप में संदर्भित किसी भी वर्ग के उदाहरण पर, और प्राप्त करें Eat विशिष्ट उपवर्ग का व्यवहार।

class Animal {
 public:
  // Intentionally not virtual:
  void Move() {
    std::cout << "This animal moves in some way" << std::endl;
  }
  virtual void Eat() = 0;
};

// The class "Animal" may possess a definition for Eat if desired.
class Llama : public Animal {
 public:
  // The non virtual function Move is inherited but not overridden.
  void Eat() override {
    std::cout << "Llamas eat grass!" << std::endl;
  }
};

यह एक प्रोग्रामर को क्लास के ऑब्जेक्ट्स की सूची को प्रोसेस करने की अनुमति देता है Animalप्रत्येक को बारी-बारी से खाने के लिए कहना (कॉल करके)। Eat), यह जानने की आवश्यकता के बिना कि सूची में किस प्रकार का जानवर हो सकता है, प्रत्येक जानवर कैसे खाता है, या संभावित प्रकार के जानवरों का पूरा सेट क्या हो सकता है।

सी में, आभासी कार्यों के पीछे का तंत्र निम्नलिखित तरीके से प्रदान किया जा सकता है:

#include <stdio.h>

/* an object points to its class... */
struct Animal {
    const struct AnimalClass * class;
};

/* which contains the virtual function Animal.Eat */
struct AnimalClass {
    void (*Eat)(struct Animal *); // 'virtual' function 
};

/* Since Animal.Move is not a virtual function
   it is not in the structure above. */
void Move(struct Animal * self)
{
    printf("<Animal at %p> moved in some way\n", (void *) self);
}

/* unlike Move, which executes Animal.Move directly,
   Eat cannot know which function (if any) to call at compile time.
   Animal.Eat can only be resolved at run time when Eat is called. */
void Eat(struct Animal * self)
{
    const struct AnimalClass * class = *(const void **) self;
    if (class->Eat) 
        class->Eat(self); // execute Animal.Eat
    else
        fprintf(stderr, "Eat not implemented\n");
}

/* implementation of Llama.Eat this is the target function 
   to be called by 'void Eat(struct Animal *).' */
static void _Llama_eat(struct Animal * self)
{
    printf("<Llama at %p> Llama's eat grass!\n", (void *) self);    
}

/* initialize class */
const struct AnimalClass Animal = {(void *) 0}; // base class does not implement Animal.Eat
const struct AnimalClass Llama = {_Llama_eat};  // but the derived class does

int main(void)
{
   /* init objects as instance of its class */
   struct Animal animal = {& Animal};
   struct Animal llama = {& Llama};
   Move(& animal); // Animal.Move
   Move(& llama);  // Llama.Move
   Eat(& animal);  // cannot resolve Animal.Eat so print "Not Implemented" to stderr
   Eat(& llama);   // resolves Llama.Eat and executes
}

सार वर्ग और शुद्ध आभासी कार्य

एक शुद्ध वर्चुअल फ़ंक्शन या शुद्ध वर्चुअल विधि एक वर्चुअल फ़ंक्शन है जिसे व्युत्पन्न वर्ग द्वारा लागू किया जाना आवश्यक है यदि व्युत्पन्न वर्ग सार प्रकार नहीं है। शुद्ध आभासी विधियों वाली कक्षाओं को सार कहा जाता है और उन्हें सीधे तत्काल नहीं किया जा सकता है। एक सार वर्ग का एक उपवर्ग (कंप्यूटर विज्ञान) केवल सीधे ही तत्काल किया जा सकता है यदि सभी विरासत में मिली शुद्ध आभासी विधियों को उस वर्ग या मूल वर्ग द्वारा लागू किया गया हो। शुद्ध आभासी तरीकों में आमतौर पर एक घोषणा (प्रकार हस्ताक्षर # विधि हस्ताक्षर) होती है और कोई परिभाषा नहीं होती है (विधि कार्यान्वयन)।

एक उदाहरण के रूप में, एक सार आधार वर्ग MathSymbol एक शुद्ध आभासी कार्य प्रदान कर सकता है doOperation(), और व्युत्पन्न वर्ग Plus और Minus अमल में लाना doOperation() ठोस कार्यान्वयन प्रदान करने के लिए। क्रियान्वयन doOperation() में कोई मतलब नहीं होगा MathSymbol वर्ग, के रूप में MathSymbol एक अमूर्त अवधारणा है जिसका व्यवहार केवल प्रत्येक दिए गए प्रकार (उपवर्ग) के लिए परिभाषित किया गया है MathSymbol. इसी तरह, एक दिया गया उपवर्ग MathSymbol के कार्यान्वयन के बिना पूरा नहीं होगा doOperation().

हालाँकि शुद्ध आभासी विधियों का आमतौर पर उस वर्ग में कोई कार्यान्वयन नहीं होता है जो उन्हें घोषित करता है, कुछ भाषाओं में शुद्ध आभासी विधियों (जैसे C ++ और पायथन) को उनके घोषित वर्ग में कार्यान्वयन शामिल करने की अनुमति है, फ़ॉलबैक या डिफ़ॉल्ट व्यवहार प्रदान करता है जिसे एक व्युत्पन्न वर्ग प्रतिनिधि कर सकता है। , अगर उचित है।[5][6] शुद्ध आभासी कार्यों का भी उपयोग किया जा सकता है जहां इंटरफ़ेस (जावा) को परिभाषित करने के लिए विधि घोषणाओं का उपयोग किया जा रहा है - जैसा कि जावा में इंटरफ़ेस कीवर्ड स्पष्ट रूप से निर्दिष्ट करता है। ऐसे उपयोग में, व्युत्पन्न वर्ग सभी कार्यान्वयनों की आपूर्ति करेगा। इस तरह के एक डिज़ाइन पैटर्न में, इंटरफ़ेस के रूप में कार्य करने वाले सार वर्ग में केवल शुद्ध आभासी कार्य होंगे, लेकिन कोई डेटा सदस्य या साधारण तरीके नहीं होंगे। सी ++ में, इंटरफेस के रूप में ऐसे पूरी तरह से सार वर्गों का उपयोग करना काम करता है क्योंकि सी ++ एकाधिक विरासत का समर्थन करता है। हालाँकि, क्योंकि कई OOP भाषाएँ एकाधिक वंशानुक्रम का समर्थन नहीं करती हैं, वे अक्सर एक अलग इंटरफ़ेस तंत्र प्रदान करते हैं। एक उदाहरण जावा (प्रोग्रामिंग भाषा) है।

निर्माण और विनाश के दौरान व्यवहार

जब किसी वस्तु का कंस्ट्रक्टर (कंप्यूटर साइंस) या डिस्ट्रक्टर (कंप्यूटर साइंस) चल रहा होता है तो भाषाएं उनके व्यवहार में भिन्न होती हैं। इस कारण से, कंस्ट्रक्टर्स में वर्चुअल फ़ंक्शंस को कॉल करना आमतौर पर हतोत्साहित किया जाता है।

सी ++ में, बेस फ़ंक्शन कहा जाता है। विशेष रूप से, सबसे अधिक व्युत्पन्न कार्य जो वर्तमान निर्माता या विध्वंसक वर्ग से अधिक व्युत्पन्न नहीं है, कहलाता है।[7]: §15.7.3 [8][9] यदि वह कार्य एक शुद्ध आभासी कार्य है, तो अपरिभाषित व्यवहार होता है।[7]: §13.4.6 [8]यह सच है भले ही कक्षा में उस शुद्ध वर्चुअल फ़ंक्शन के लिए कार्यान्वयन हो, क्योंकि शुद्ध वर्चुअल फ़ंक्शन के लिए कॉल स्पष्ट रूप से योग्य होना चाहिए।[10] संकलन समय या लिंक समय पर शुद्ध आभासी कार्यों के लिए अप्रत्यक्ष कॉल का पता लगाने के लिए एक अनुरूप सी ++ कार्यान्वयन की आवश्यकता नहीं है (और आमतौर पर सक्षम नहीं)। रनटाइम (प्रोग्राम लाइफसाइकिल चरण) पर शुद्ध वर्चुअल फ़ंक्शन के लिए कॉल का सामना करते समय कुछ रनटाइम सिस्टम शुद्ध वर्चुअल फ़ंक्शन कॉल त्रुटि जारी करेंगे।

जावा और सी # में, व्युत्पन्न कार्यान्वयन कहा जाता है, लेकिन कुछ क्षेत्रों को अभी तक व्युत्पन्न कन्स्ट्रक्टर द्वारा प्रारंभ नहीं किया गया है (हालांकि वे अपने डिफ़ॉल्ट शून्य मानों में प्रारंभ किए गए हैं)।[11] कुछ डिज़ाइन पैटर्न (कंप्यूटर विज्ञान), जैसे सार फैक्टरी पैटर्न, इस क्षमता का समर्थन करने वाली भाषाओं में सक्रिय रूप से इस उपयोग को बढ़ावा देते हैं।

आभासी विनाशक

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

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

यह भी देखें

संदर्भ

  1. "Polymorphism (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)". docs.oracle.com. Retrieved 2020-07-11.
  2. "9. Classes — Python 3.9.2 documentation". docs.python.org. Retrieved 2021-02-23.
  3. "Writing Final Classes and Methods (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)". docs.oracle.com. Retrieved 2020-07-11.
  4. "PHP: Final Keyword - Manual". www.php.net. Retrieved 2020-07-11.
  5. Pure virtual destructors - cppreference.com
  6. "abc — Abstract Base Classes: @abc.abstractmethod"
  7. 7.0 7.1 "N4659: Working Draft, Standard for Programming Language C++" (PDF).
  8. 8.0 8.1 Chen, Raymond (April 28, 2004). "What is __purecall?".
  9. Meyers, Scott (June 6, 2005). "Never Call Virtual Functions during Construction or Destruction".
  10. Chen, Raymond (October 11, 2013). "C++ corner case: You can implement pure virtual functions in the base class".
  11. Ganesh, S.G. (August 1, 2011). "Joy of Programming: Calling Virtual Functions from Constructors".