2009-05-07 3 views
8

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

उत्तर

7

एक फ़ंक्शन केवल वर्चुअल होने की आवश्यकता है यदि एक व्युत्पन्न वर्ग उस कार्य को एक अलग तरीके से लागू करेगा।

उदाहरण के लिए:

class Base { 
public: 
    void setI (int i) // No need for it to be virtual 
    { 
    m_i = i; 
    } 

    virtual ~Base() {}   // Almost always a good idea 

    virtual bool isDerived1() // Is overridden - so make it virtual 
    { 
    return false; 
    } 

private: 
    int m_i; 
}; 

class Derived1 : public Base { 
public: 
    virtual ~Derived() {} 

    virtual bool isDerived1() // Is overridden - so make it virtual 
    { 
    return true; 
    } 
}; 

नतीजतन, मैं कुछ भी आभासी नहीं होने जब तक आप पहले से पता है कि आप इसे ओवरराइड करने का इरादा या जब तक आप है कि आप व्यवहार की आवश्यकता होती की खोज की ओर त्रुटि होगी। इसका एकमात्र अपवाद विनाशक है, जिसके लिए लगभग हमेशा यह मामला है कि आप इसे बेस क्लास में वर्चुअल होना चाहते हैं।

+1

जब कक्षा में कम से कम एक विधि आभासी है तो आपके पास वर्चुअल विनाशक होना चाहिए। – stefanB

0

इंटरफ़ेस फ़ंक्शन सामान्य रूप से आभासी होना चाहिए। फ़ंक्शंस जो निश्चित कार्यक्षमता प्रदान नहीं करते हैं।

2

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

ओह, और स्पष्ट रूप से हमेशा अपने विनाशक वर्चुअल को बनाते हैं यदि आप किसी ऐसे चीज़ पर काम कर रहे हैं जो विरासत में मिलेगा।

0

कुछ वर्चुअल क्यों घोषित करें जब तक आप वास्तव में इसे ओवरराइड नहीं कर रहे हों? मेरा मानना ​​है कि यह सुनिश्चित करने का सवाल नहीं है या नहीं। तथ्यों का पालन करें: क्या यह कहीं अधिक है? नहीं? फिर यह आभासी नहीं होना चाहिए।

+0

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

+1

तो आईएमओ विधियों को आभासी iff subclasses को ओवरराइड करने की अनुमति है (और रनटाइम बहुरूपता समर्थित है), अगर वे वास्तव में नहीं करते हैं। –

1

आप एक आधार वर्ग (आप यह सुनिश्चित करें कि किसी वर्ग निकला हैं) तो आप निम्नलिखित बातें कर सकते हैं बना रहे हैं:

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

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

टीएलडीआर संस्करण: "आपके पास वर्चुअल फ़ंक्शंस का सेट होना चाहिए और गैर वर्चुअल फ़ंक्शंस का एक सेट होना चाहिए जो आपको यकीन है कि विरासत में नहीं जा रहे हैं।" क्योंकि वर्चुअल फ़ंक्शंस रन-टाइम पर प्रदर्शन घटता है।

4

आपको केवल वही कार्य करना चाहिए जो आप वर्चुअल वर्चुअल होने के लिए इच्छित हैं। एक विधि वर्चुअल बनाना रखरखाव और प्रदर्शन दोनों के मामले में मुक्त नहीं है (रखरखाव आईएमएचओ का बड़ा मुद्दा है)।

एक बार विधि आभासी होने के बाद इस विधि का उपयोग करने वाले किसी भी कोड के बारे में तर्क करना कठिन हो जाता है।क्योंकि एक विधि कॉल करने पर विचार करने के बजाय, आपको यह समझना चाहिए कि उस परिदृश्य में एन विधि कॉल क्या करेंगे। एन उस वर्ग को ओवरराइड करने वाले उप वर्गों की संख्या का प्रतिनिधित्व करता है।

इस नियम का एक अपवाद विनाशक है। वे किसी भी वर्ग में आभासी होना चाहिए जिसका उद्देश्य से लिया जाना है। यह गारंटी देने का एकमात्र तरीका है कि उचित विनाशक को विलोपन के दौरान बुलाया जाता है।

4

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

+0

यहां स्रोत जोड़ने पर विचार करें। पता चला कि आप "सी ++ कोडिंग मानकों, 101 नियम, दिशानिर्देश और सर्वोत्तम अभ्यास, हर्ब सटर और Andrej Alexandrescu" का उल्लेख करते हैं। हालांकि, सी ++ में कोई आधिकारिक कोडिंग मानक नहीं है। – patrik

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