2010-07-22 13 views
5

मैं एक सी ++ इंटरफ़ेस को परिभाषित क्यों करना चाहता हूं जिसमें निजी विधियां हों?सी ++ इंटरफ़ेस में निजी विधि?

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

क्या यह एक इंटरफेस के मूल उपयोग से एक विचलन नहीं है, यानी बाहरी और आंतरिक के बीच एक सार्वजनिक अनुबंध?

आप एक मित्र वर्ग भी परिभाषित कर सकते हैं, जो हमारी कक्षा से कुछ निजी तरीकों का उपयोग करेगा, और इंटरफेस के माध्यम से कार्यान्वयन को मजबूर करेगा। यह एक तर्क हो सकता है।

सी ++ में किसी इंटरफ़ेस के भीतर निजी विधियों को परिभाषित करने के लिए अन्य तर्क क्या हैं?

+1

इंटरफ़ेस! = सार्वजनिक सदस्य। आपका इंटरफ़ेस आपका _documentation_ है, न कि आपकी हेडर फ़ाइल। –

उत्तर

6

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

  • कैसे इंटरफ़ेस
  • क्या पाने कक्षाएं प्रयोग की जाने वाली चाहिए की पेशकश

इस सेल्सियस के लिए विशेष रूप से कुछ अर्थों में ++ है, जहां इंटरफ़ेस वास्तव में कोड शामिल कर सकते हैं कि --how उपयोगकर्ताओं को देखने बाहरी इंटरफ़ेस me-- से adapts (एकाधिक विरासत के साथ किसी भी भाषा के लिए वास्तव में) और आंतरिक इंटरफेस - मैं कैसे लागू किया गया है।

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

दूसरा आम उपयोग कि NVI मुहावरा का उपयोग करके, यह आसान साधन के लिए एक ही आधार स्तर पर संशोधित करके कोड है:

class Base { 
public: 
    void foo() { 
     foo_impl(); 
    } 
private: 
    virtual void foo_impl() = 0; 
}; 

डिस्पैचर foo() { foo_impl(); } लिखने के लिए होने के अतिरिक्त लागत के बजाय है छोटे और यह आपको लॉकिंग तंत्र को बाद में जोड़ने की अनुमति देता है यदि आप कोड को मल्टीथ्रेड किए गए एप्लिकेशन में परिवर्तित करते हैं, प्रत्येक कॉल में लॉगिंग जोड़ते हैं, या टाइमर को यह सत्यापित करने के लिए कि प्रत्येक फ़ंक्शन में कितने अलग कार्यान्वयन होते हैं ... चूंकि वास्तविक विधि लागू की गई है व्युत्पन्न कक्षाओं में इस स्तर पर निजी है, आपको गारंटी है कि सभी पॉलीमोर्फिक कॉलों को एक बिंदु पर वाद्य यंत्रित किया जा सकता है: आधार (यह कक्षाओं को विस्तारित नहीं करता है foo_impl बनाने सार्वजनिक सोचा)

void Base::foo() { 
    scoped_log log("calling foo"); // we can add traces 
    lock l(mutex);     // thread safety 
    foo_impl(); 
} 

तो आभासी तरीकों सार्वजनिक थे, तो आप तरीकों के लिए सभी कॉल अवरोधन नहीं कर सकता है और सभी व्युत्पन्न वर्ग कि इंटरफ़ेस को लागू करने के लिए कि लॉगिंग और धागा सुरक्षा जोड़ना होगा ।

3

आप एक निजी आभासी विधि घोषित कर सकते हैं जिसका उद्देश्य व्युत्पन्न होना है। उदाहरण:

class CharacterDrawer { 
public: 
    virtual ~CharacterDrawer() = 0; 

    // draws the character after calling getPosition(), getAnimation(), etc. 
    void draw(GraphicsContext&); 

    // other methods 
    void setLightPosition(const Vector&); 

    enum Animation { 
     ... 
    }; 

private: 
    virtual Vector getPosition() = 0; 
    virtual Quaternion getRotation() = 0; 
    virtual Animation getAnimation() = 0; 
    virtual float getAnimationPercent() = 0; 
}; 

इस वस्तु एक चरित्र के लिए उपयोगिता ड्राइंग प्रदान कर सकते हैं, लेकिन है आदि एक वस्तु जो आंदोलन, एनीमेशन हैंडलिंग प्रदान करता है,

provinding के बजाय इस तरह कर रही है का लाभ "द्वारा derivated जा करने के लिए setPosition "," setAnimation "इत्यादि यह है कि आपको प्रत्येक फ्रेम पर मान को" पुश "करने की आवश्यकता नहीं है, इसके बजाय आप इसे" खींचें "।

मुझे लगता है कि इसे एक इंटरफेस के रूप में माना जा सकता है क्योंकि इन विधियों के पास सभी ड्राइंग से संबंधित सामानों के वास्तविक कार्यान्वयन के साथ कुछ लेना देना नहीं है।

0

एक टेम्पलेट विधि कार्यान्वयन में, इसका उपयोग विशेषज्ञता बाधा जोड़ने के लिए किया जा सकता है: आप व्युत्पन्न वर्ग से बेस क्लास की वर्चुअल विधि को कॉल नहीं कर सकते हैं (अन्यथा, विधि को बेस क्लास में संरक्षित घोषित किया जाएगा):

class Base 
{ 
private: 
    virtual void V() { /*some logic here, not accessible directly from Derived*/} 
}; 

class Derived: public Base 
{ 
private: 
    virtual void V() 
    { 
     Base::V(); // Not allowed: Base::V is not visible from Derived 
    } 
}; 
3

क्यों मैं एक सी ++ इंटरफ़ेस है कि निजी तरीकों में शामिल है को परिभाषित करना चाहते हैं?

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

मुझे लगता है कि आपका प्रश्न एक इंटरफेस के साथ एक सार आधार वर्ग को भ्रमित करने से आता है (अगर मैं गलत हूं तो कृपया मुझे सही करें)।

एक सार आधार वर्ग आंशिक (या यहां तक ​​कि पूर्ण) कार्यक्षमता कार्यान्वयन भी हो सकता है, जिसमें कम से कम एक सार सदस्य है। इस मामले में, यह निजी सदस्यों के लिए जितना अधिक समझ में आता है क्योंकि यह किसी अन्य वर्ग के लिए बनाता है।

अभ्यास में शुद्ध वर्चुअल बेस क्लास को किसी भी कार्यान्वयन के साथ शायद ही कभी आवश्यकता होती है (यानी बेस क्लास जो शुद्ध वर्चुअल फ़ंक्शंस की सूची को परिभाषित करते हैं और कुछ और नहीं)। एक मामला जहां आवश्यक है COM/DCOM/XPCOM प्रोग्रामिंग (और अन्य भी हैं)। ज्यादातर मामलों में हालांकि यह आपके सार आधार वर्ग में कुछ निजी कार्यान्वयन जोड़ने के लिए समझ में आता है।

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