आपको सी ++ के कई अजीब कोनों में से एक का सामना करना पड़ा है। इस मामले में सी ++ अलग-अलग वर्गों से विरासत में दो वर्चुअल फ़ंक्शंस को समान कार्य करने के लिए नहीं मानता है, भले ही उनके पास समान नाम और प्रकार हस्ताक्षर हो।
इस तरह से कार्य करने के लिए सी ++ के कुछ अच्छे कारण हैं। उदाहरण के लिए, अक्सर यह मामला होता है कि वास्तव में वही नाम और प्रकार हस्ताक्षर के बावजूद वे दो कार्य वास्तव में समान नहीं हैं। दो कार्यों का अर्थपूर्ण अर्थ अलग है।
यहाँ एक उदाहरण है:
namespace vendor1 {
class Circle {
public:
virtual ::std::size_t size() const { return sizeof(*this); }
};
} // namespace vendor1
namespace vendor2 {
class Shape {
public:
virtual double size() const = 0;
};
class Circle : public Shape {
public:
virtual double size() const { return radius_ * radius_ * M_PI; }
};
} // namespace vendor2
और फिर आप इस प्रयास करें:
namespace my_namespace {
class Circle : public ::vendor1::Circle, public ::vendor2::Circle {
// Oops, there is no good definition for size
};
तो आप इस का सहारा लेना है:
namespace my_namespace {
class Vendor1Circle : public ::vendor1::Circle {
public:
virtual ::std::size_t data_structure_size() const { return size(); }
};
class Vendor2Circle : public ::vendor2::Circle {
public:
virtual double area() const { return size(); }
};
class Circle : public Vendor1Circle, public Vendor2Circle {
// Now size is still ambiguous and should stay that way
// And in my opinion the compiler should issue a warning if you try
// to redefine it
};
तो, सी ++ अच्छा कारण है एक ही प्रकार के हस्ताक्षर के साथ आभासी कार्यों का इलाज करने के लिए (वापसी प्रकार प्रकार हस्ताक्षर का हिस्सा नहीं है) और दो differe से नाम विभिन्न कार्यों के रूप में एनटी आधार।
जहां तक using
चला जाता है ... सभी using
निर्देश कहते हैं, "इस नामस्थान से इस नामस्थान में नाम जोड़ें जैसे कि यहां घोषित किया गया था।"। जहां तक आभासी कार्यों का संबंध है, यह एक शून्य अवधारणा है। यह केवल सुझाव देता है कि नाम का उपयोग करते समय किसी भी अस्पष्टता को एक अलग तरीके से हल किया जाना चाहिए। यह केवल एक नाम घोषित करता है, यह नाम परिभाषित नहीं करता है। वर्चुअल फ़ंक्शन को ओवरराइड करने के लिए एक नई परिभाषा की आवश्यकता होती है।
OTOH, अगर आप इस तरह इनलाइन एक सरल thunk परिभाषा में डाल अगर:
class Bar : public Foo, public Goo {
public:
virtual DerivedElem& get_elem() { return Goo::get_elem(); }
};
एक अच्छा संकलक है कि देख सकते हैं और यहां तक कि समारोह बनाने के लिए परेशान नहीं करने के लिए पता होना चाहिए, और इसके बजाय सिर्फ आभासी तालिका प्रविष्टियों बेला सही काम करने के लिए। इसे वास्तव में इसके लिए कोड उत्सर्जित करने की आवश्यकता हो सकती है और उसके पते के मामले में प्रतीक उपलब्ध हो सकता है, लेकिन Foo *
के माध्यम से कॉल किए जाने पर यह कार्य को पूरी तरह गायब होने में वर्चुअल तालिका को आसानी से खराब करने में सक्षम होना चाहिए।
साफ, छोटा, आत्मनिर्भर उदाहरण। मैं चाहता हूं कि जिनके पास कोड कोड था, उन्होंने जो किया वह सब किया। – Omnifarious
क्या कॉवरेन्ट रिटर्न प्रकारों के लिए गुओ को फू से नहीं लिया जाना चाहिए? – Chubsdad
हाय दोस्तों, त्वरित और सहायक प्रतिक्रियाओं के लिए धन्यवाद। पॉलिमॉर्फिक असाइनमेंट स्टीव के बारे में अच्छी युक्ति। यदि कोई सोच रहा था कि मैं इस तरह की संरचना क्यों देख रहा हूं, तो मेरे वास्तविक कोड 'गू' में एक टेम्पलेट क्लास है जिसे बाद के टेम्पलेट वर्गों द्वारा विरासत में मिला है और 'फू' श्रेणी वर्गों तक पहुंचने के लिए 'इंटरफ़ेस' है। – Tom