क्या Derived1 :: Base और Derived2 :: Base समान प्रकार को संदर्भित करता है?


12

इस कोड पर MSVC, Clang और GCC असहमत हैं:

struct Base { int x; };
struct Der1 : public  Base {};
struct Der2 : public  Base {};

struct AllDer : public Der1, public Der2 {
    void foo() {
        Der1::Base::x = 5;
    }
};

Godbolt

जीसीसी:

<source>: In member function 'void AllDer::foo()':    
<source>:10:21: error: 'Base' is an ambiguous base of 'AllDer'    
   10 |         Der1::Base::x = 5;    
      |                     ^    
Compiler returned: 1

क्लेंग एक समान त्रुटि देता है, और MSVC कोई त्रुटि नहीं देता है।

यहाँ कौन सही है?

मुझे लगता है कि यह [class.member.lookup] में कवर किया गया है , लेकिन मुझे यह समझने में कठिनाई है कि यह मुझे इस मामले के लिए क्या बताने की कोशिश कर रहा है। कृपया संबंधित भागों को उद्धृत करें और यदि संभव हो तो सादे अंग्रेजी में समझाएं।

पुनश्च: इस प्रश्न से प्रेरित है कि बेस क्लास के संदर्भ में अस्पष्ट के साथ :: -ऑपरेटर गर्त व्युत्पन्न वर्ग क्यों है?

PPS: वास्तव में मेरा संदेह यह है कि क्या Der1::Baseप्रकार को संदर्भित करता है, जो होगा Base(और फिर Der2::Baseठीक उसी प्रकार का है), या उप-विषय पर। मुझे विश्वास है कि यह पहला है, लेकिन अगर यह बाद का है तो MSVC सही होगा।



@LanguageLawyer अधिक अच्छे संकेत देते हैं कि gcc और clang सही हैं, लेकिन मैं पूरी तरह से आश्वस्त नहीं हूं कि mscv गलत है
idclev 463035818

1
जाहिर है कि दोनों एक ही प्रकार के हैं ::Base, लेकिन असली सवाल यहां थोड़ा अलग है। दो प्रकार के उप-विषय हैं Base, और दोनों में एक Base::x सदस्य है।
एमएसलटर्स

@ पीएलएस पीपीएस केवल मेरे भ्रम को व्यक्त करता है। यदि आपके पास बेहतर शीर्षक के लिए एक सुझाव है कि आप इसे संपादित करने के लिए स्वतंत्र महसूस कर रहे हैं, तो मुझे यह पसंद नहीं है (क्योंकि मुझे पता है कि इसका उत्तर हां है), लेकिन कुछ और उपयुक्त नहीं मिला
idclev 463035818

1
@ d4rk4ng31 कोड में कोई आभासी विरासत नहीं है (उद्देश्य पर)
idclev 463035818

जवाबों:


6

शीर्षक में प्रश्न का उत्तर देने के लिए, हाँ, इंजेक्शन-वर्ग-नाम [class.pre] और इसी तरह का Derived1::Baseसंदर्भ देता है । दोनों वर्ग का उल्लेख करते हैं । BaseDerived2::Base::Base

अब, यदि Baseकोई स्थैतिक सदस्य होगा x, तो उसकी तलाश Base::xअस्पष्ट होगी। वहाँ सिर्फ एक है।

इस उदाहरण में समस्या यह है कि है xएक गैर स्थिर सदस्य है, और AllDerहै दो तरह के सदस्य हैं। आप के लिए इस तरह का उपयोग को स्पष्ट कर सकते हैं xएक निर्दिष्ट द्वारा स्पष्ट आधार वर्ग के AllDerजो केवल एक ही है xसदस्य। Derived1एक असंदिग्ध आधार वर्ग है, और इसका एक xसदस्य है, इसलिए Derived1::xअसंदिग्ध रूप से निर्दिष्ट करता है कि आप xमें से कौन सा दो सदस्य हैं AllDerBaseभी केवल एक ही हैx सदस्य है, लेकिन यह एक आधार नहीं है AllDer। हर प्रकार की AllDerदो उप-वस्तुएँ होती हैं Base। इसलिए Base::xआपके उदाहरण में अस्पष्ट है। और चूँकि इसके Derived1::Baseलिए सिर्फ एक और नाम है Base, यह अस्पष्ट है।

[class.member.lookup] निर्दिष्ट है कि xनेस्टेड-नेम- स्पेसियर के संदर्भ में देखा जाता है, इसलिए इसे पहले हल करना होगा। हम वास्तव में देख रहे Base::x, नहीं Derived1::x, क्योंकि हम को हल करने के द्वारा शुरू Derived1::Baseके रूप में Base। इस भाग सफल होता है, वहाँ केवल एक ही है xमें Base.नोट 12 [class.member.lookup] में स्पष्ट रूप से आपको बताती है कि स्पष्ट नाम देखने का उपयोग कर एक अभी भी विफल हो सकता है कि जब वहाँ है कि एक ही नाम के साथ कई subobjects हैं।D::iउस उदाहरण में मूल रूप से आपका है Base::x


इसलिए यह केवल "विफल हो सकता है" लेकिन "असफल नहीं होना चाहिए" और सभी तीन संकलक सही हैं? के template <typname A,typename B> struct foo : A,Bआधार के सदस्यों का उपयोग करने के लिए कुछ वंचित कोड के साथ उदाहरण के लिए विचार करें Aऔर B। ऐसे मामले में मैं एक त्रुटि प्राप्त करना चाहता हूं
idclev 463035818

1
@ idclev463035818: मुझे संदेह है कि यह एक "विफल" निदान आवश्यक है । विशेष रूप से, यह 7.6.1.4/7 वर्ग सदस्य पहुंच, "बीमार-गठन" पर विफल रहता है।
MSalters

मुझे थोड़ा और पढ़ना है। और मुझे msvc पर कुछ शोध करना है, मुझे संदेह है कि कुछ झंडों को पूरी तरह से आउटपुट प्राप्त करने के लिए आवश्यक है, लेकिन यह पता लगाना होगा कि कौन से झंडे
idclev 463035818

2

कक्षा के एक सदस्य के रूप में आप वर्ग के नाम का उल्लेख कर सकते हैं, क्योंकि cpp उपनाम सुविधाजनक उपयोग के लिए है, जैसे कि आपने using Base = ::Base;बेस के अंदर लिखा है।
आप जिस समस्या का सामना कर रहे हैं, वह Der1::Baseहै Base
इस प्रकार, जब आप लिखते हैं Der1::Base::x, तो यह वैसा ही होता है Base::x


मुझे पता है कि "समस्या" क्या है, लेकिन आप मेरे सवाल का जवाब नहीं दे रहे हैं: "कौन सही है? (और क्यों?)"
idclev 463035818

@ idclev463035818: मेरा मानना ​​है कि यह सही पक्ष है। के बारे usingमें हिस्सा मानक में लिखा है, और मुझे लगता है कि अभिव्यक्ति की व्याख्या करने की कुंजी है।
दानी

@ idclev463035818: निम्नलिखित उदाहरण देखें। मुझे लगता है कि यह इसे थोड़ा साफ कर देगा। ideone.com/IqpXjT
दानी

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

बस FYI करें, MSVC (x64 के लिए 19.25.28614) ideone.com/IqpXjT पर आपके उदाहरण को संकलित करने में विफल रहता है । cl /c /Wall /WX /Od /MDd /Za /permissive- /std:c++17 main.cppइसकी कमांड लाइन के रूप में उपयोग करते हुए , मुझे मिलता हैmain.cpp(7): error C2597: illegal reference to non-static member 'A::x'
हीप
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.