c++ - सी++ आभासी कार्यों को सुरक्षित रूप से ओवरराइड करें




override virtual-functions (6)

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

यह उदाहरण लें:

class parent {
public:
  virtual void handle_event(int something) const {
    // boring default code
  }
};

class child : public parent {
public:
  virtual void handle_event(int something) {
    // new exciting code
  }
};

int main() {
  parent *p = new child();
  p->handle_event(1);
}

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

क्या इस समस्या से बचने का कोई तरीका है, क्या मैं किसी भी तरह से मेरे लिए यह जांचने के लिए कंपाइलर या कुछ अन्य टूल बता सकता हूं? कोई सहायक कंपाइलर झंडे (अधिमानतः जी ++ के लिए)? आप इन समस्याओं से कैसे बचते हैं?


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

उदाहरण के लिए, यह माइक्रोसॉफ्ट विजुअल सी ++ में सी 4263 चेतावनी दे रहा है।


एमएसवीसी ++ में आप कीवर्ड override उपयोग कर सकते override

    class child : public parent {
    public:
      virtual void handle_event(int something) override {
        // new exciting code
      }
    };

एमएसवीसी ++ में देशी और सीएलआर कोड दोनों के लिए override काम करता है।


चूंकि जी ++ 4.7 यह नए सी ++ 11 override कीवर्ड को समझता है:

class child : public parent {
    public:
      // force handle_event to override a existing function in parent
      // error out if the function with the correct signature does not exist
      void handle_event(int something) override;
};

जहां तक ​​मुझे पता है, क्या आप इसे अमूर्त नहीं बना सकते?

class parent {
public:
  virtual void handle_event(int something) const = 0 {
    // boring default code
  }
};

मैंने सोचा कि मैं www.parashift.com पर पढ़ता हूं कि आप वास्तव में एक अमूर्त विधि को कार्यान्वित कर सकते हैं। जो मुझे व्यक्तिगत रूप से समझ में आता है, केवल एक चीज है जो इसे लागू करने के लिए उप-वर्गों को मजबूर करती है, किसी ने इसके बारे में कुछ भी नहीं कहा है, इसे कार्यान्वित करने की अनुमति नहीं दी जा रही है।


मैं आपके तर्क में थोड़ा बदलाव का सुझाव दूंगा। आपको जो करना है उसे पूरा करने के आधार पर यह काम कर सकता है या नहीं भी।

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

संपादित करें: और यदि आप बाद में निर्णय लेते हैं कि आपके कुछ वंशज वर्गों को "नया रोमांचक कोड" प्रदान करने की आवश्यकता नहीं है तो आप सार को आभासी में बदल सकते हैं और उस "सम्मिलित" कार्यक्षमता के खाली बेस क्लास कार्यान्वयन की आपूर्ति कर सकते हैं।


सी # के override कीवर्ड की तरह कुछ सी ++ का हिस्सा नहीं है।

जीसीसी में, -Woverloaded-virtual वर्चुअल फ़ंक्शन को एक ही नाम के फ़ंक्शन के साथ छिपाने के खिलाफ चेतावनी देता है लेकिन पर्याप्त रूप से अलग हस्ताक्षर है कि यह इसे ओवरराइड नहीं करता है। हालांकि, फ़ंक्शन नाम को गलत वर्तनी के कारण किसी फ़ंक्शन को ओवरराइड करने में विफल होने के बावजूद यह आपकी रक्षा नहीं करेगा।





virtual-functions