2009-07-28 15 views
8

वर्चुअल बेस क्लास में डेटा सदस्यों को न रखने की अनुशंसा क्यों की जाती है?वर्चुअल बेस क्लास डेटा सदस्य

फ़ंक्शन सदस्यों के बारे में क्या? यदि मेरे पास सभी व्युत्पन्न कक्षाओं के लिए एक कार्य सामान्य है, तो वर्चुअल बेस क्लास के लिए यह कार्य करना ठीक है या व्युत्पन्न उत्तराधिकारी को दो वर्गों से प्राप्त करना चाहिए - वर्चुअल इंटरफ़ेस से और सादा आधार जो कार्य करता है?

धन्यवाद।

+6

आप सलाह के लिए एक लिंक या प्रशस्ति पत्र प्रदान किया जा सका मैं नहीं कर सकता।? बेस क्लास वर्चुअल को चिह्नित करने में बहुत अधिक बिंदु देखें यदि उसके पास डेटा सदस्य नहीं हैं, क्योंकि वर्चुअल विरासत का सबसे आम उद्देश्य बेस क्लास सदस्यों के डुप्लिकेशन को रोकना है। उदाहरण के लिए मानक पुस्तकालयों में, ios_base में डेटा सदस्य हैं, और यह एक हैआइसट्रीम और ओस्ट्रीम दोनों के वर्चुअल बेस क्लास (आईओएस के माध्यम से)। तो मैं लगभग (लेकिन काफी नहीं) रिवर्स कहूंगा - यदि आपके पास वर्चुअल बेस क्लास होगा, तो इसमें डेटा सदस्य होना चाहिए, या अन्यथा गैर-वर्चुअल रूप से प्राप्त होना चाहिए। –

उत्तर

11

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

वर्चुअल विरासत के साथ सबसे बड़ी कमी यह है कि उनके निर्माता पैरामीटर लेते हैं। यदि आपको वर्चुअल बेस क्लास के कन्स्ट्रक्टर को पैरामीटर पास करना है तो आप सभी व्युत्पन्न कक्षाओं को कन्स्ट्रक्टर को स्पष्ट रूप से कॉल करने के लिए मजबूर करते हैं (वे कन्स्ट्रक्टर को कॉल करने वाले बेस क्लास पर भरोसा नहीं कर सकते हैं)।

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

मार्टिन की टिप्पणी के बाद मैंने कुछ घर का काम किया, धन्यवाद मैरिन। पहली पंक्ति पूरी तरह सच नहीं है:

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

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

Non virtual virtual 
    A  A   A 
    |  |  / \ 
    B  C  B  C 
    \ /  \ /
    D    D 

आभासी मामले बी में अगर आधार वर्ग डेटा है एक असली फर्क नहीं पड़ता, और सी ए

का एक ही प्रति साझा

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

+0

+1 यह सी ++ एफएक्यू लाइट http://www.new-brunswick.net/workshop/c++/faq/multiple-inheritance.html#faq-25.8 –

+0

पर भी संक्षेप में है, मुझे लगता है कि इनमें से कोई भी सच नहीं है। –

+0

@ मार्टिन: दुख की बात है, यह है ... –

0

क) के सदस्यों को निजी होना चाहिए - ताकि आप उन्हें व्युत्पन्न वर्ग में का उपयोग कर (ताकि आप मनुष्य और सेटर तरीके, जो अपने इंटरफेस को उड़ाने)

ख जोड़ने के लिए समस्याओं मिल सकता है) नहीं घोषित करते हैं कि आप चीजों वर्तमान में उपयोग नहीं करते हैं - केवल कक्षाओं में चर घोषित जो पहुँच/उन्हें

ग) का उपयोग आभासी आधार वर्ग केवल इंटरफेस/आभासी तरीकों, को शामिल करना चाहिए और कुछ नहीं

मुझे आशा है कि भले ही, एक छोटा सा मदद करता है मेरे कारण सही और पूर्ण नहीं हैं :)

Ciao, क्रिस

1

मैंने कभी भी यह सिफारिश नहीं देखी है।

एक कक्षा निकट से संबंधित कार्यों और डेटा का एक सेट है। बेस क्लास का उद्देश्य उन कार्यों और डेटा का एक सामान्य सेट होना है जो व्युत्पन्न कक्षाओं द्वारा पुन: उपयोग के लिए उपलब्ध हैं।

मुझे लगता है कि बेस क्लास में डेटा सदस्यों या गैर-शुद्ध वर्चुअल फ़ंक्शंस रखने के लिए खुद को प्रतिबंधित करना कोड पुन: उपयोग की मात्रा को कम करेगा, जो लंबे समय तक कम विश्वसनीय कोड की ओर जाता है।

+1

यदि आप "प्रभावी सी ++" की एक प्रति प्राप्त कर सकते हैं, तो आइटम 20 पढ़ें: "सार्वजनिक इंटरफेस में डेटा सदस्यों से बचें"। – quark

+0

ठीक है, मैं इसके साथ सहमत हूं। मैं सुझाव नहीं दे रहा हूं कि डेटा सदस्य सार्वजनिक हों। किसी भी मामले में, मैंने सवाल को गलत समझा, और लगता है कि इयान का जवाब अच्छा है। –

2

मूल सलाह वर्चुअल बेस में डिफ़ॉल्ट-निर्माता है। आप नहीं करते हैं, तो हर सबसे व्युत्पन्न वर्ग (यानी। किसी भी उपवर्ग) आभासी आधार ctor स्पष्ट रूप से कॉल करना होगा, और कहा कि अपने कार्यालय के दरवाजे पर दस्तक नाराज सहयोगियों की ओर जाता है ...

class VirtualBase { 
public: 
    explicit VirtualBase(int i) : m_i(i) {} 
    virtual ~VirtualBase() {} 

private: 
    int m_i; 
}; 

class Derived : public virtual VirtualBase { 
public: 
    Derived() : VirtualBase(0) {} // ok, this is to be expected 
}; 

class DerivedDerived : public Derived { // no VirtualBase visible 
public: 
    DerivedDerived() : Derived() {} // ok? no: error: need to explicitly 
            // call VirtualBase::VirtualBase!! 
    DerivedDerived() : VirtualBase(0), Derived() {} // ok 
}; 
+0

आपका मतलब है कि अगर मैंने वर्चुअल बेस सीटीआर को स्पष्ट रूप से कॉल नहीं किया है तो इसे व्युत्पन्न ऑब्जेक्ट बनाने पर नहीं कहा जाएगा? – jackhab

+0

_hach_ व्युत्पन्न ctor के कार्यान्वयन में वर्चुअल बेस क्लास ctor को कॉल करने के लिए _have_, संकलक आपको अन्यथा इससे दूर जाने नहीं देगा। एकमात्र अपवाद: यदि वर्चुअल बेस में एक डिफ़ॉल्ट ctor है, तो उस व्यक्ति को बुलाया जाता है जब आप स्पष्ट रूप से किसी अन्य को कॉल नहीं करते हैं। –

0

सभी - सी ++ में इंटरफेस को अनुकरण करने के लिए उपयोग की जाने वाली बेस क्लास को डेटा सदस्यों के पास नहीं होना चाहिए - क्योंकि वे इंटरफ़ेस का वर्णन कर रहे हैं, और उदाहरण स्थिति एक कार्यान्वयन विवरण है।

इसके अलावा, वर्चुअल फ़ंक्शंस वाले बेस क्लास में डेटा सदस्य भी हो सकते हैं। सामान्य नियम लागू होते हैं, हालांकि:

  • उन्हें जितना संभव हो उतना छुपा बनाते हैं, और यदि आप कक्षा आविष्कारों को संरक्षित करने की आवश्यकता है तो गेटर्स और सेटर्स का उपयोग करें। , इससे इनकार करते हैं एक व्युत्पन्न वर्ग एक अपरिवर्तनीय जोड़ने वहाँ, सदस्य के साथ जुड़े यानी यह किसी भी समय किसी भी संभावित मूल्य मान सकते हैं कोई अपरिवर्तनीय है, तो आप इसे सार्वजनिक कर सकता है हालांकि
  • :
    (यहाँ में उपाय बता रहे हैं।। विरासत के लिए डिजाइन: अपने वर्ग के अनुबंध जिम्मेदारियों और एक व्युत्पन्न वर्ग की संभावनाओं परिभाषित करना चाहिए, यह क्या जरूरत है/क्या प्रयोजन के लिए अधिलेखित कर सकते हैं
संबंधित मुद्दे