2010-09-09 7 views
19

मेरा कोड है -व्युत्पन्न * से आधार * के बीच रूपांतरण निजी विरासत के साथ विफल क्यों होगा?

#include<iostream> 
using namespace std; 

class base 
{ 
public: 
    void sid() 
    { 
    } 
}; 

class derived : private base 
{ 
public: 
    void sid() 
    { 
    } 
}; 

int main() 
{ 
    base * ptr; 
    ptr = new derived; // error: 'base' is an inaccessible base of 'derived' 
    ptr->sid(); 
    return 0; 
} 

यह संकलन समय त्रुटि देता है।

error: 'base' is an inaccessible base of 'derived' 

चूंकि संकलक बेस क्लास sid() को आज़माकर कॉल करेगा और मुझे यह त्रुटि क्यों मिलती है? क्या कोई इसे समझा सकता है।

+0

आपने विधि 'वर्चुअल' घोषित नहीं किया था। आप वास्तव में क्या त्रुटि प्राप्त कर रहे हैं? – Dirk

+8

अपने वर्तमान रूप में इसमें फ़ंक्शन 'sid()' के साथ कुछ लेना देना नहीं है। आप निजी विरासत का उपयोग कर रहे हैं इसलिए 'व्युत्पन्न *' से 'आधार *' में रूपांतरण विफल हो रहा है। क्या आप यही पूछ रहे हैं या यह विधि 'sid() 'के साथ कुछ करना है? – Naveen

+1

[संरक्षित व्युत्पन्न वर्ग] के संभावित डुप्लिकेट (http://stackoverflow.com/questions/433965/protected-derived-class) – kennytm

उत्तर

16

$ 11,2/4 राज्यों

A base class B of N is accessible at R, if

  • an invented public member of B would be a public member of N, or
  • R occurs in a member or friend of class N, and an invented public member of B would be a private or protected member of N, or
  • R occurs in a member or friend of a class P derived from N, and an invented public member of B would be a private or protected member of P, or
  • there exists a class S such that B is a base class of S accessible at R and S is a base class of N accessible at R."

यहाँ 'बी' 'बेस' है, 'एन' 'व्युत्पन्न' है और 'आर' मुख्य है।

  1. दूसरी बुलेट पर विचार करें- 'आर किसी सदस्य या कक्षा एन के मित्र में होता है ...'। यह खंड 'आर' (मुख्य) के रूप में लागू नहीं होता है न तो सदस्य और न ही 'एन' (व्युत्पन्न)

  2. तीसरी बुलेट पर विचार करें- 'आर किसी सदस्य या कक्षा पी के मित्र में होता है ... । '। इस क्लॉस भी रूप में ऊपर

  3. 4 bullet- पर विचार एक ही कारण के लिए लागू नहीं होता है एक बार फिर से इस खंड पर लागू नहीं होता

इस प्रकार हम निष्कर्ष निकाल सकते हैं कि 'आधार' का एक सुलभ वर्ग नहीं है 'निकाली गई'।

$ 11,2/5 राज्यों -

If a base class is accessible, one can implicitly convert a pointer to a derived class to a pointer to that base class (4.10, 4.11). [ Note: it follows that members and friends of a class X can implicitly convert an X* to a pointer to a private or protected immediate base class of X. —end note ]

Base के बाद से Derived का एक सुलभ वर्ग नहीं है जब main में पहुँचा, बेस वर्ग के लिए व्युत्पन्न वर्ग से मानक रूपांतरण बीमार का गठन है। इसलिए त्रुटि।

संपादित करें 2:

अध्ययन कुछ लोकप्रिय compilers की त्रुटि संदेश और है कि आप एक बेहतर समझ पाने में मदद मिलेगी।ध्यान दें कि 'त्रुटि पहुंच' शब्द कितनी बार और लगातार सभी त्रुटि संदेशों में पॉप-अप करता है

संदर्भ ड्राफ्ट मानक N3000 से हैं। मैं अभी तक नवीनतम मसौदा :)

GCC prog.cpp: In function ‘int main()’: prog.cpp:27: error: ‘base’ is an inaccessible base of ‘derived’

Comeau Online "ComeauTest.c", line 26: error: conversion to inaccessible base class "base" is not allowed ptr = new derived;

VS2010 error C2243: 'type cast' : conversion from 'derived *' to 'base *' exists, but is inaccessible

+0

क्या आप कृपया अपना संदर्भ प्रदान कर सकते हैं। – Bruce

+0

@ ब्रूस: ओह क्षमा करें, मैं यह उल्लेख करना भूल गया कि संदर्भ ड्राफ्ट मानक एन 3000 से हैं। मैंने पाया कि सी ++ 03 में इस अवधारणा को समझने के लिए कुछ भ्रमित बयान हैं। मैं – Chubsdad

+0

के अनुसार अपनी पोस्ट अपडेट करूँगा डगलस लीडर और मानव पठनीय और त्वरित समाधान के लिए ereOn के जवाब देखें। – mwjohnson

35

मुझे संदेह है कि समस्या यह है कि आप एक व्युत्पन्न सूचक को आधार सूचक में परिवर्तित नहीं कर सकते हैं, क्योंकि विरासत निजी है।

+0

मैं ऐसा क्यों नहीं कर सकता? इसमें कार्यान्वयन की समस्याएं क्या हैं? – Bruce

+2

निजी विरासत का अर्थ है कि आप नहीं चाहते कि बेस क्लास इंटरफ़ेस बाल कोड कोड की तुलना में अन्य कोड तक पहुंच योग्य हो। – Klaim

+7

वास्तव में चब्सदाद के जवाब की व्याख्या करने में समय व्यतीत करने की तरह महसूस नहीं किया था और यह वही था जो मुझे जानने की आवश्यकता थी। मेरी व्युत्पन्न कक्षा परिभाषा – User

0

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

+4

पर एक 'सार्वजनिक' कथन गायब था, आप जानते हैं, जब लोग डाउनवोट करते हैं, तो मैं उससे नफरत करता हूं, और कोई टिप्पणी नहीं छोड़ता। –

+0

मैंने इस उत्तर को कम मत दिया, लेकिन मुझे लगता है कि यह गलत है। मैंने कंपाइलर्स को एक व्युत्पन्न-श्रेणी वाले एक बेस-क्लास फ़ंक्शन को छिपाने के लिए * चेतावनियां * दी हैं, लेकिन कभी भी कोई त्रुटि नहीं है। –

5

इस प्रयास करें:

#include<iostream> 
#include<conio.h> 
using namespace std; 

class base 
{ 
     private: 
     public: 
      virtual void sid() // You might want to declare sid virtual 
      { 
        cout<<"base"; 
      } 
      virtual ~base() // You then probably need a virtual destructor as well. 
      { 
      } 
}; 

class derived : public base //public inheritance 
{ 
     private: 
     public: 
      void sid() 
      { 
        cout<<"derived"; 
      } 
}; 

int main() 
{ 
    base * ptr; 
    ptr = new derived; 
    ptr->sid(); 
    getch(); 
    return 0; 
} 
+0

आपका मतलब 'वर्चुअल शून्य एसआईडी() 'था? इसके अलावा आपको बेस क्लास विनाशक को 'वर्चुअल' होने की आवश्यकता है। – Naveen

+0

@ नवीन: धन्यवाद। मैं विनाशक को जोड़ने के अपने रास्ते पर था;) इसके अलावा, 'निजी' एक टाइपो था। – ereOn

+0

वर्चुअल विनाशक एक अच्छा विचार है। सिड फ़ंक्शन पर वर्चुअल डालना मूल पोस्टर के एक निर्दिष्ट लक्ष्य के विपरीत है। –

6

तुम्हें पता है कि class base से class derived इनहेरिट करती है, लेकिन main() समारोह में यह नहीं जानता है। main() फ़ंक्शन का कारण यह नहीं है कि आपने class derived को class base से निजी रूप से प्राप्त किया है।

इसलिए जब आप new derivedptr पर असाइन करने का प्रयास करते हैं, तो पॉइंटर प्रकार संगत नहीं होते हैं।

+0

@WP: क्या आप कृपया अपने उत्तर – Bruce

+0

पर विस्तृत कर सकते हैं Chubsdad ... –

8

Chusbad मानक से जुड़े बारे में गहराई से स्पष्टीकरण प्रदान की डाउनलोड करने के लिए कर रहा हूँ, मैं एक सुलभ विवरण प्रदान करने की कोशिश करेंगे।

सी ++ में, 3 एक्सेस लेवल विनिर्देशक हैं: public, protected और private। वे यह निर्धारित करने के लिए हैं कि डब्ल्यूएचओ विधियों, विशेषताओं या आधार वर्गों तक कैसे पहुंच सकता है। यह ऑब्जेक्ट ओरिएंटेड भाषाओं के बीच विशिष्ट है।

यहां, आपने private विरासत चुना है। संकल्पनात्मक रूप से इसका मतलब यह है कि आप इस तथ्य को छिपाने की कोशिश करते हैं कि Derived बाहरी लोगों को Base से विरासत में मिलता है, जिसका आमतौर पर अर्थ है कि यह एक कार्यान्वयन विवरण है।

परिणामस्वरूप, "बाहरी" इस संबंध से अनजान है। यह इस inaccessible संदेश के साथ संकलक द्वारा लागू किया गया है।

एक डिजाइन बिंदु से, private विरासत आमतौर पर आवश्यक नहीं है। या तो लिस्कोव प्रतिस्थापन सिद्धांत लागू होता है और आप public विरासत का उपयोग करते हैं, या तो यह एक कार्यान्वयन विवरण है और आप संरचना का उपयोग करते हैं।

0

यह त्रुटि देता है C2243: 'टाइप कास्ट': 'व्युत्पन्न *' से 'बेस *' में रूपांतरण मौजूद है, लेकिन पहुंच योग्य यह व्युत्पन्न वर्ग निजी रूप से विरासत में मिला है। इसलिए प्राप्त होने पर बेस क्लास ऑब्जेक्ट नहीं बनाया जाता है सृजन होता है। व्युत्पन्न वस्तु बनाने के लिए पहली कॉल बेस क्लास ऑब्जेक्ट बनाने के लिए जाती है जो नहीं हो रहा है। सोल्यूशन कक्षा को सार्वजनिक रूप से प्राप्त करना है। इससे कोई फर्क नहीं पड़ता कि आप वर्चुअल कीवर्ड का उपयोग सदस्य कार्यों के साथ करते हैं या नहीं।

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