2012-04-20 19 views
5

बेस क्लास A में उप-वर्ग B है, और B में उप-वर्ग C है। A वर्चुअल विधि doStuff() लागू करता है, B नहीं करता है, और C करता है। C से, मैं A कॉल करना चाहते हैं '(रों doStuff() के कार्यान्वयन doStuff() की रों कार्यान्वयन मैं C से कर' लेकिन यह है कि वास्तव में कोई फर्क नहीं करना चाहिए।) मैं बुलाना चाहिए:बेस क्लास

A::doStuff(); 

या:

B::doStuff(); 

पहला स्पष्ट लगता है क्योंकि यह वास्तविक कार्यान्वयन को संदर्भित करता है। दूसरी तरफ, दूसरा और अधिक उपयोगी हो सकता है यदि मैंने बाद में B को A से अलग की आवश्यकता है। कौन सा मानक है? कौन सा खतरनाक है?

मुझे आश्चर्य हुआ कि B::doStuff() ने कोई चेतावनी ट्रिगर नहीं की है, लेकिन मुझे लगता है कि परिभाषा B के आधार पर यह भी है कि यह बेस क्लास से है। क्या आधार वर्गों और कार्यान्वयन की श्रृंखला मनमाने ढंग से लंबी और जटिल हो सकती है? उदाहरण के लिए, अगर AZ के माध्यम से, प्रत्येक पिछले के उप-वर्ग में, क्या मैं श्रृंखला में कहीं भी कार्यान्वयन कर सकता हूं, और किसी वर्ग की विधि को कॉल करने से यह केवल 'चेन अप' तक जाता है जब तक कि इसे कार्यान्वयन नहीं मिल जाता?

उत्तर

2

सबसे पहले, अंतिम पैराग्राफ के संबंध में, हाँ, आप बिल्कुल सही हैं।

आगे, मुख्य प्रश्न के लिए:

यह तर्क की बात जो एक मामले के लिए दर-मामला आधार पर इलाज किया जाना चाहिए है। आप केवल एक ही हैं जो यह तय कर सकते हैं कि आप तर्क को B से या A से कॉल करना चाहते हैं, भले ही B::doStuff() अभी तक लागू नहीं हुआ है। कोई सही जवाब नहीं है।

हालांकि, आपको टेम्पलेट विधि पैटर्न में देखना चाहिए। मेरा अनुमान है कि यदि आप A से कुछ कॉल करने के लिए चाहते हैं और बाद में आप यह तय करते हैं कि आप D (C का भाई) एक ही काम करने के लिए चाहते हैं, तो आप कोड डुप्लिकेट कर रहे हैं। तो मैं एक अलग दृष्टिकोण लेगा:

class A 
{ 
private: 
    void doAStuff(); //doesn't have to be here 
public: 
    virtual void doStuff() 
    { 
     doAStuff(); 
    } 
    void doAStuffAndStuff(); 
    { 
     doAStuff(); 
     doStuff(); 
    } 
} 

class B : A 
{ 
public: 
    virtual void doStuff(); //or not 
} 

class C : B 
{ 
public: 
    virtual void doStuff(); 
} 

आईएमओ यह अधिक सहज है।

  • अगर मैं सबसे व्युत्पन्न वर्ग में तर्क के साथ doStuff() कॉल करना चाहते हैं, मैं फोन doStuff(): मैं a के गतिशील प्रकार पता नहीं है मैं एक A* a है कहते हैं,।
  • यदि मैं सबसे अधिक व्युत्पन्न कक्षा में तर्क के साथ doStuff() पर कॉल करना चाहता हूं, लेकिन मुझे A से तर्क भी चाहिए, तो मैं doAStuffAndStuff() पर कॉल करता हूं।

मैं इस दृष्टिकोण को एक विकल्प के रूप में बता रहा हूं। मैं यह नहीं कह रहा हूं कि यह आपके मामले पर लागू होता है, लेकिन यह हो सकता है।

+0

यह एक बहुत साफ और उपयोगी विकल्प की तरह दिखता है। – Luke

0

कॉल B::doStuff पर कॉल करें। इससे भी बेहतर, उन डिज़ाइनों का उपयोग न करें जिन्हें बेस क्लास के तरीकों को स्पष्ट रूप से कॉल करने की आवश्यकता है, यदि आप कर सकते हैं।यदि आपको जरूरी है कि वास्तव में ऐसी त्रुटियों से बचने के लिए कुछ मैक्रो या उपनाम निर्माण द्वारा base.doStuff अनुकरण करें। आप कक्षा में BaseType कक्षा में एक उपनाम परिभाषित कर सकते हैं (और संकलन समय पर इसकी उपस्थिति सुनिश्चित कर सकते हैं और BaseType::doStuff वाक्यविन्यास का उपयोग कर सकते हैं।

मैं एक छोटे से हैरान हूँ कि बी :: doStuff() कोई चेतावनी को ट्रिगर नहीं किया था, लेकिन मुझे लगता है

है द्वारा परिभाषा बी एक कार्यान्वयन भले ही वह आधार वर्ग से है है चेतावनी देने के लिए कुछ नहीं। यह आपके मामले में एक कानूनी परिदृश्य है।

आधार वर्ग और कार्यान्वयन की श्रृंखला मनमाने ढंग से लंबे और जटिल

हाँ, यह कर सकते हैं हो सकता है, लेकिन यह नहीं करना चाहिए। जिन डिज़ाइनों को लंबी विरासत श्रृंखलाओं की आवश्यकता होती है, उनमें कुछ प्रकार के छिपे नियम होते हैं जो बेस क्लास को किस प्रकार बुलाया जाना चाहिए, आमतौर पर टूटा हुआ होता है।

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