C ++ में शब्द "इंटरफ़ेस"


11

जावा classऔर के बीच एक स्पष्ट अंतर बनाता है interface। (मेरा मानना ​​है कि C # भी करता है, लेकिन मुझे इसका कोई अनुभव नहीं है)। C ++ लिखते समय हालांकि कक्षा और इंटरफ़ेस के बीच कोई भाषा लागू नहीं है।

नतीजतन मैंने हमेशा जावा में कई विरासत की कमी के लिए इंटरफ़ेस को देखा है। इस तरह का भेद करना C ++ में मनमाना और अर्थहीन लगता है।

मैंने हमेशा "चीजों को सबसे स्पष्ट तरीके से लिखने" दृष्टिकोण के साथ जाना है, इसलिए यदि C ++ में मुझे जावा में एक इंटरफ़ेस कहा जा सकता है, जैसे:

class Foo {
public:
  virtual void doStuff() = 0;
  ~Foo() = 0;
};

और फिर मैंने फैसला किया कि अधिकांश कार्यान्वयनकर्ता Fooकुछ सामान्य कार्यक्षमता साझा करना चाहते हैं जो मैं शायद लिखूंगा:

class Foo {
public:
  virtual void doStuff() = 0;
  ~Foo() {}
protected:
  // If it needs this to do its thing:
  int internalHelperThing(int);
  // Or if it doesn't need the this pointer:
  static int someOtherHelper(int);
};

जो तब जावा इंटरफ़ेस में इसे इंटरफ़ेस नहीं बनाता है।

इसके बजाय C ++ की दो महत्वपूर्ण अवधारणाएं हैं, जो एक ही अंतर्निहित विरासत समस्या से संबंधित हैं:

  1. virtual inhertiance
  2. आधार के रूप में उपयोग किए जाने पर बिना सदस्य चर वाली कक्षाएं कोई अतिरिक्त स्थान नहीं ले सकती हैं

    "बेस क्लास सबोबेज में शून्य आकार हो सकता है"

    संदर्भ

उन लोगों में से मैं जहाँ भी संभव हो # 1 से बचने की कोशिश करता हूं - यह एक परिदृश्य का सामना करना दुर्लभ है जहां यह वास्तव में "सबसे साफ" डिजाइन है। # 2 हालांकि "इंटरफ़ेस" और C ++ भाषा सुविधाओं की मेरी समझ के बीच एक सूक्ष्म, लेकिन महत्वपूर्ण अंतर है। इस के परिणामस्वरूप मैं वर्तमान में (लगभग) सी ++ में "इंटरफेस" के रूप में चीजों को संदर्भित नहीं करता हूं और आधार वर्गों और उनके आकारों के संदर्भ में बात करता हूं। मैं कहूंगा कि C ++ "इंटरफ़ेस" के संदर्भ में एक मिथ्या नाम है।

यह मेरे ध्यान में आया है कि बहुत से लोग इस तरह का भेद नहीं करते हैं।

  1. क्या मैं (जैसे protected) गैर- virtualफ़ंक्शंस को C ++ में "इंटरफ़ेस" में मौजूद होने की अनुमति देकर कुछ भी खोने के लिए खड़ा हूं ? (मेरी भावना बिल्कुल विपरीत है - साझा कोड के लिए एक अधिक प्राकृतिक स्थान)
  2. क्या "इंटरफ़ेस" शब्द C ++ में सार्थक है - क्या इसका अर्थ केवल शुद्ध है virtualया यह C ++ वर्ग को कॉल करने के लिए उचित होगा, जिसमें कोई सदस्य अभी भी इंटरफ़ेस नहीं रखता है ?

सी # एक ही है इंटरफेस, कार्यान्वयन की एक उत्तराधिकार के एकाधिक वंशानुक्रम जावा के रूप में है, लेकिन के उपयोग के माध्यम सामान्य विस्तार के तरीकों , internalHelperThingलगभग सभी मामलों में नकली जा सकता है।
Sjoerd

ध्यान दें कि आभासी सदस्यों को बेनकाब करना बुरा है।
Klaim

एक ~Foo() {}अमूर्त वर्ग में एक सार्वजनिक हर परिस्थिति में (लगभग) एक त्रुटि है।
वुल्फ

जवाबों:


11

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

अपने उदाहरण के बारे में: जावा में (और C # में समान), आपका कोड संभवतः चिंताओं का अलगाव होगा:

interface IFoo {/*  ... */} // here is your interface

class FooBase implements IFoo 
{
     // make default implementations for interface methods
}

class Foo extends FooBase
{
}

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


3
सी + + प्रोग्रामर के लिए "इंटरफ़ेस" का एक और संभावित अर्थ, फ़ाइल के publicकुछ भाग हैं .h
डेविड थॉर्नले

आपका कोड किस भाषा का उदाहरण है? अगर वह C ++ होने का एक प्रयास है तो मैं रोने वाला हूं ...
Qix - MONICA WIST MISTREATED

@Qix: इसे आसान बनाए रखें, मेरी पोस्टिंग को फिर से पढ़ें (यह स्पष्ट रूप से बताता है कि कोड जावा में है), और अगर आपको मिला> 2000 अंक, तो आप मेरे पोस्ट को बराबर C ++ उदाहरण कोड जोड़ने के लिए संपादित कर सकते हैं, जिससे मेरा उदाहरण और अधिक हो सके स्पष्ट।
डॉक्टर ब्राउन 12

अगर यह जावा है, तो यह अभी भी गलत है, और नहीं मैं इसे संपादित नहीं कर सकता; बदलने के लिए पर्याप्त वर्ण नहीं। जावा कॉलन को लागू करने / विस्तार करने में उपयोग नहीं करता है, यही कारण है कि मैं सोच रहा था कि क्या यह C ++ पर एक प्रयास था ...
Qix - MONICA WIST MISTREATED

@Qix: यदि आपको अधिक वाक्यात्मक मुद्दे मिलते हैं, तो आप उन्हें एक क्रिसमस के रूप में प्रस्तुत कर सकते हैं :-)
डॉक्टर ब्राउन

7

यह थोड़ा ऐसा लगता है जैसे आप इस अर्थ को भ्रमित करने के जाल में पड़ गए होंगे कि यह क्या है कि एक इंटरफ़ेस वैचारिक रूप से कार्यान्वयन (इंटरफ़ेस - लोअरकेस 'i) दोनों के रूप में है, और एक अमूर्त (एक इंटरफ़ेस - अपरकेस "I') )।

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

इंटरफेसेस को अक्सर उन भाषाओं के लिए "वर्क-अराउंड" के रूप में जाना जाता है जो कई उत्तराधिकार का समर्थन नहीं करते हैं, लेकिन मुझे लगता है कि यह एक कठिन सच्चाई से अधिक गलत धारणा है (और मुझे संदेह है कि मैं इसे बताते हुए भड़क सकता हूं!)। इंटरफेसेस का वास्तव में कई उत्तराधिकारियों से कोई लेना-देना नहीं है कि उन्हें कक्षाओं के बीच कार्यात्मक अनुकूलता प्रदान करने, या कक्षाओं के लिए अमूर्तता प्रदान करने के लिए विरासत में या तो पूर्वजों के होने की आवश्यकता नहीं है। वास्तव में, वे आपको प्रभावी ढंग से विरासत के साथ दूर करने की अनुमति दे सकते हैं पूरी तरह से आपको अपना कोड उस तरह से लागू करना चाहिए - ऐसा नहीं है कि मैं पूरी तरह से इसकी सिफारिश करूंगा, लेकिन मैं सिर्फ यह कह रहा हूं कि आप कर सकते हैंकर दो। तो वास्तविकता यह है कि वंशानुक्रम के मामलों की परवाह किए बिना, इंटरफेसेस एक साधन प्रदान करते हैं जिसके द्वारा वर्ग-प्रकार परिभाषित किए जा सकते हैं, उन नियमों को स्थापित करना जो निर्धारित करते हैं कि वस्तुएं एक-दूसरे के साथ कैसे संवाद कर सकती हैं, इस प्रकार वे आपको यह निर्धारित करने की अनुमति देते हैं कि आपके वर्गों को बिना व्यवहार का समर्थन करना चाहिए। उस व्यवहार को लागू करने के लिए उपयोग की जाने वाली विशिष्ट विधि को निर्धारित करना।

क्या मैं C ++ में "इंटरफ़ेस" के भीतर मौजूद गैर-वर्चुअल फ़ंक्शंस की अनुमति देकर (जैसे संरक्षित) गैर-वर्चुअल फ़ंक्शन को खोने के लिए खड़ा हूं? (मेरी भावना बिल्कुल विपरीत है - साझा कोड के लिए एक अधिक प्राकृतिक स्थान)

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

क्या "इंटरफ़ेस" शब्द C ++ में सार्थक है - क्या इसका अर्थ केवल शुद्ध आभासी है या यह C ++ वर्ग को कॉल करने के लिए उचित होगा जहां कोई सदस्य अभी भी एक इंटरफ़ेस नहीं रखता है?

मुझे माफ़ कर दो, लेकिन मुझे C ++ में एक गंभीर आवेदन लिखने के बाद से यह एक लंबा समय हो गया है। मुझे याद है कि इंटरफ़ेस अमूर्त के प्रयोजनों के लिए एक खोजशब्द है जैसा कि मैंने उन्हें यहाँ बताया है। मैं किसी भी प्रकार के C ++ वर्गों को इंटरफ़ेस नहीं कहूंगा, मैं कहूंगा कि कक्षा का अर्थ है कि मैंने ऊपर उल्लिखित अर्थों के भीतर एक इंटरफ़ेस है। उस अर्थ में आईएस शब्द सार्थक है, लेकिन यह वास्तव में संदर्भ पर निर्भर करता है।


1
+1 में "होने" और "होने" के बीच अंतर है।
डॉक्टर ब्राउन

6

जावा इंटरफेस एक "वर्कअराउंड" नहीं है, वे हीरे की विरासत जैसी कई विरासत के साथ कुछ समस्याओं से बचने के लिए और युग्मन को कम करने वाले डिजाइन प्रथाओं को प्रोत्साहित करने के लिए एक जानबूझकर डिजाइन निर्णय हैं।

संरक्षित विधियों के साथ आपका इंटरफ़ेस "उत्तराधिकार पर रचना पसंद करने" की आवश्यकता का एक पाठ्यपुस्तक मामला है। अपने उत्कृष्ट C ++ कोडिंग मानकों से उस नाम के अनुभाग में Sutter और Alexandrescu से उद्धृत करने के लिए :

इनहेरिटेंस टैक्स से बचें: इनहेरिटेंस C ++ में दूसरा सबसे मजबूत कपलिंग संबंध है, केवल दोस्ती के लिए दूसरा। तंग युग्मन अवांछनीय है और जहां संभव हो वहां से बचना चाहिए। इसलिए, जब तक आप जानते हैं कि रचना वास्तव में आपके डिजाइन को लाभ देती है, तब तक विरासत की रचना को प्राथमिकता दें।

अपने इंटरफ़ेस में अपने सहायक कार्यों को शामिल करके, आप अब थोड़ा टाइपिंग बचा सकते हैं, लेकिन आप युग्मन पेश कर रहे हैं जो आपको सड़क पर चोट पहुंचाएगा। अपने सहायक कार्यों को अलग बनाने और पास करने के लिए लगभग हमेशा बेहतर दीर्घकालिक होता है Foo*

एसटीएल इसका एक बहुत अच्छा उदाहरण है। जहां तक ​​संभव हो सके कई सहायक कार्य <algorithm>कंटेनर कक्षाओं में होने के बजाय बाहर खींच लिए जाते हैं। उदाहरण के लिए, चूंकि sort()अपना काम करने के लिए सार्वजनिक कंटेनर एपीआई का उपयोग करता है, आप जानते हैं कि आप किसी भी एसटीएल कोड को बदलने के बिना अपने स्वयं के सॉर्टिंग एल्गोरिदम को लागू कर सकते हैं। यह डिज़ाइन पुस्तकालयों को बढ़ावा देने में सक्षम बनाता है, जो इसे बदलने के बजाय एसटीएल को बढ़ाते हैं, एसटीएल को बढ़ावा के बारे में कुछ भी जानने की आवश्यकता के बिना।


2

क्या मैं C ++ में "इंटरफ़ेस" के भीतर मौजूद गैर-वर्चुअल फ़ंक्शंस की अनुमति देकर (जैसे संरक्षित) गैर-वर्चुअल फ़ंक्शन को खोने के लिए खड़ा हूं? (मेरी भावना बिल्कुल विपरीत है - साझा कोड के लिए एक अधिक प्राकृतिक स्थान)

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

यह उन उदाहरणों में से एक है जहां एक-आकार-फिट-सभी उत्तर नहीं है और आपको निर्णय लेने के लिए अपने अनुभव और निर्णय का उपयोग करना होगा। यदि आप 100% विश्वास के साथ कह सकते हैं कि आपके अन्यथा पूरी तरह से आभासी वर्ग के हर संभव उपवर्ग Fooको हमेशा संरक्षित पद्धति के कार्यान्वयन की आवश्यकता होगी bar(), तो Fooइसके लिए सही जगह है। एक बार जब आपके पास एक उपवर्ग Bazहोता है bar(), जिसकी आपको आवश्यकता नहीं होती है , तो आपको या तो इस तथ्य के साथ रहना Bazहोगा कि आपके पास अपनी कक्षा पदानुक्रम को पुन: व्यवस्थित करने के अभ्यास के माध्यम से कोड होना चाहिए या नहीं होना चाहिए। पूर्व अच्छा अभ्यास नहीं है और बाद में कुछ ही मिनटों से अधिक समय लग सकता है जो चीजों को पहले से ठीक से व्यवस्थित करने में ले जाएगा।

क्या "इंटरफ़ेस" शब्द C ++ में सार्थक है - क्या इसका अर्थ केवल शुद्ध आभासी है या यह C ++ वर्ग को कॉल करने के लिए उचित होगा जहां कोई सदस्य अभी भी एक इंटरफ़ेस नहीं रखता है?

C ++ मानक की धारा 10.4, इंटरफेस को लागू करने के लिए अमूर्त वर्गों के उपयोग का एक गुजर उल्लेख करता है, लेकिन उन्हें औपचारिक रूप से परिभाषित नहीं करता है। यह शब्द एक सामान्य कंप्यूटर विज्ञान के संदर्भ में सार्थक है, और किसी भी सक्षम को समझना चाहिए कि " Foo(जो भी हो) के लिए एक इंटरफ़ेस है" का अर्थ है अमूर्तता के कुछ रूप। परिभाषित इंटरफ़ेस निर्माण के साथ भाषाओं के संपर्क में आने वाले लोग शुद्ध आभासी सोच सकते हैं, लेकिन वास्तव में काम करने वाले किसी व्यक्ति को Fooआगे बढ़ने से पहले इसकी परिभाषा पर गौर करना चाहिए।


2
शुद्ध वर्चुअल डिक्लेरेशन और डिक्लेरेशन प्लस लागू करने में क्या अंतर है? दोनों ही मामलों में, एक कार्यान्वयन होना चाहिए, और bazहमेशा एक कार्यान्वयन हो सकता है जैसे return false;या जो भी हो। यदि विधि सभी उपवर्गों पर लागू नहीं होती है, तो यह किसी भी रूप में आधार सार वर्ग में नहीं है।
डेविड थॉर्नले

1
मुझे लगता है कि आपका अंतिम वाक्य कहता है कि हम एक ही पृष्ठ पर हैं: ऐसा कोई कारण नहीं है कि आपके पास अमूर्त कक्षाओं में संरक्षित तरीके नहीं हो सकते हैं, लेकिन वे वंशानुक्रम के पेड़ में बिल्कुल आवश्यक से अधिक नहीं होना चाहिए। मैं सिर्फ यह सोचता हूं कि अगर किसी वर्ग को क्रियान्वयन में कमी करनी है, तो वह पेड़ में सही जगह पर नहीं है।
ब्लर एफएल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.