2011-08-23 17 views
5

मैंने जीएसएल के कुछ हिस्सों के आसपास थोड़ा सी ++ रैपर लिखा और निम्नलिखित पहेली (मेरे लिए) का सामना किया। कोड (अपने अनिवार्य करने के लिए कम) इस प्रकार है:सुपर क्लास (मूल्य से गुजरने) के कारण ओवरलोडेड कन्स्ट्रक्टर की संदिग्ध कॉल

#include <stdlib.h> 
    struct gsl_vector_view {}; 

    class Vector : protected gsl_vector_view { 
      public: 
      Vector (const Vector& original); 
      Vector (const gsl_vector_view view); 
    }; 

    class AutoVector : public Vector { 
      public: 
      explicit AutoVector (const size_t dims); 
    }; 

    void useVector (const Vector b) {} 

    void test() { 
      const AutoVector ov(2); 
      useVector(ov); 
    } 

जीसीसी 4.4.5 जी ++ -c v.cpp का उपयोग कर संकलन नहीं होगा लेकिन उपज

 In function ‘void test()’: 
    19: error: call of overloaded ‘Vector(const AutoVector&)’ is ambiguous 
    7: note: candidates are: Vector::Vector(gsl_vector_view) 
    6: note:     Vector::Vector(const Vector&) 
    19: error: initializing argument 1 of ‘void useVector(Vector)’ 

मैं हैरान हूं कि संरक्षित आधार वर्ग gsl_vector_view उपयोग वेक्टर (वेक्टर) के कॉल द्वारा विचार में लिया जाता है। मैंने सोचा होगा कि उपयोग वेक्टर "द सी ++ प्रोग्रामिंग लैंग्वेज", तीसरी ई।, पी के अनुपालन में "आम जनता" से संबंधित है। 405 और इस प्रकार उस संरक्षित जानकारी तक पहुंच नहीं है और इसलिए, इससे भ्रमित नहीं किया जा सकता है। मुझे पता है कि मैं

explicit Vector (const gsl_vector_view view); 

क्या मुझे नहीं पता था के रूप में निर्माता की घोषणा (ईमानदारी से और, या तो समझ में नहीं आता) द्वारा अस्पष्टता से छुटकारा मिल सकता है, कि अतिभारित कॉल की अस्पष्टता गायब हो जाता है जब मैं है

Vector (const gsl_vector_view& view); 

यानी संदर्भ द्वारा तर्क (जिसे मैं चीजों को करने का उचित तरीका मानता हूं) के रूप में घोषित करता हूं।

+0

+1, इसका 'संरक्षित' विरासत से कोई लेना देना नहीं है; तो सवाल को दोबारा सुधारना। – iammilind

+0

बीटीडब्ल्यू। अस्पष्टता गायब हो जाती है जब आप संदर्भ लेने के लिए वेक्टर को भी घोषित करते हैं – PlasmaHH

उत्तर

4

ओवरलोड रिज़ॉल्यूशन एक्सेस जांच से पहले किया जाता है, यही कारण है कि संरक्षित बेस क्लास के सदस्यों को भी माना जाता है।

अधिभार संकल्प मानक के अध्याय 13.3 में वर्णित है। मेरी व्याख्या यह है कि बाध्यकारी const AutoVector ov से Vector (const Vector& original);उपयोगकर्ता परिभाषित रूपांतरण, व्युत्पन्न-से-आधार रूपांतरण ([13.3.3.1.4/1]) प्रकार है। Vector (const gsl_vector_view view); के लिए, रूपांतरण अनुक्रम भी उपयोगकर्ता परिभाषित रूपांतरण है क्योंकि यह lvalue-to-rvalue रूपांतरण है जिसके बाद उपयोगकर्ता परिभाषित रूपांतरण है। इसलिए, दोनों रूपांतरण अनुक्रमों को बराबर माना जाता है, कोई भी दूसरे की तुलना में बेहतर नहीं होता है, और इस प्रकार आपको अस्पष्टता मिलती है।

अब, अगर आप Vector (const gsl_vector_view& view); को ctor बदलने के लिए, दोनों रूपांतरण lvalue करने वाली मूल्य उपयोगकर्ता परिभाषित रूपांतरण (व्युत्पन्न-टू-बेस रूपांतरण) के बाद रूपांतरण कर रहे हैं। उन दोनों को आदेश दिया जा सकता है ([13.3.3.2/4]) और const Vector& में रूपांतरण बेहतर माना जाता है और इस प्रकार कोई अस्पष्टता नहीं है।

1

प्रश्न protected विरासत या कन्स्ट्रक्टर के साथ ऐसा नहीं करना है। यह समस्या सामान्य फ़ंक्शन कॉल के साथ भी जारी रहेगी (जो भी विरासत के साथ)।

जब आप सभी अधिभार संस्करणों में संदर्भ से गुज़र रहे हैं, तो निकटतम बेस क्लास चुना जाता है (यदि 1 से अधिक बेस क्लास हैं जो निकटतम हैं तो यह बीमार है)।

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

§ 13.3.1 (5)
...गैर-स्थैतिक सदस्य कार्यों के लिए रेफ-क्वालीफायर के बिना घोषित किया गया है, एक अतिरिक्त नियम लागू होता है: - भले ही अंतर्निहित ऑब्जेक्ट पैरामीटर कॉन्स्ट-क्वालिटी नहीं है, तब तक एक रावल पैरामीटर तक बाध्य किया जा सकता है जब तक कि अन्य सभी सम्मानों में तर्क निहित ऑब्जेक्ट पैरामीटर के प्रकार में परिवर्तित हो सकता है।

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