क्या केवल फ़ंक्शन ओवरलोडिंग के लिए C ++ कंपाइलर का उपयोग करना बुरा है?


60

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

कहा जा रहा है कि, कुछ स्थान हैं जहाँ मैं फंक्शन ओवरलोडिंग (C ++ की सुविधा) करता हूं। मुझे कुछ अलग प्रकार के डेटा भेजने की जरूरत है और printfकिसी भी तरह के %s(या जो भी) तर्क के साथ शैली प्रारूपण का उपयोग करने का मन नहीं है । मैंने कुछ ऐसे लोगों को देखा है जिनके पास C ++ कंपाइलर की पहुँच नहीं है printf, लेकिन मेरे मामले में C ++ का समर्थन उपलब्ध है।

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

unsigned char*
const char*
unsigned char
const char

मैं सिर्फ एक ही तरीका नहीं अपनाना चाहूंगा जो इन सभी चीजों को संभालता हो। जब मैं फ़ंक्शन पर कॉल करता हूं, तो मैं चाहता हूं कि यह सीरियल पोर्ट को प्रसारित करे, मेरे पास बहुत सारे संसाधन नहीं हैं इसलिए मैं मुश्किल से कुछ भी नहीं करना चाहता हूं लेकिन मेरा प्रसारण।

किसी और ने मेरा कार्यक्रम देखा और मुझसे पूछा, "आप CPP फ़ाइलों का उपयोग क्यों कर रहे हैं?" तो, यह मेरा एकमात्र कारण है। क्या वह बुरी प्रथा है?

अपडेट करें

मैं पूछे गए कुछ प्रश्नों को संबोधित करना चाहूंगा:

आपकी दुविधा का एक वस्तुनिष्ठ उत्तर इस पर निर्भर करेगा:

  1. यदि आप C ++ का उपयोग करते हैं, तो निष्पादन योग्य का आकार काफी बढ़ जाता है।

अभी तक निष्पादन योग्य का आकार 4.0% प्रोग्राम मेमोरी (5248 बाइट्स में से) और 8.3% डेटा मेमोरी (342 बाइट्स में से) का उपभोग करता है। यही है, सी ++ के लिए संकलन ... मुझे नहीं पता कि यह सी के लिए कैसा लगेगा क्योंकि मैं सी कंपाइलर का उपयोग नहीं कर रहा हूं। मुझे पता है कि यह कार्यक्रम और अधिक नहीं बढ़ेगा, इसलिए संसाधनों को सीमित करने के लिए मैं कहूंगा कि मैं वहां ठीक हूं ...

  1. यदि आप C ++ का उपयोग करते हैं तो प्रदर्शन पर कोई ध्यान देने योग्य नकारात्मक प्रभाव पड़ता है।

अगर वहाँ है, तो मैं कुछ भी ध्यान नहीं दिया है ... लेकिन फिर से हो सकता है कि मैं यह सवाल पूछ रहा हूँ क्योंकि मैं पूरी तरह से समझ में नहीं आता है।

  1. क्या कोड का पुन: उपयोग किसी अन्य प्लेटफ़ॉर्म पर किया जा सकता है जहाँ केवल C कंपाइलर उपलब्ध है।

मुझे पता है कि इसका जवाब निश्चित रूप से नहीं है । हम वास्तव में एक अलग प्रोसेसर पर जाने पर विचार कर रहे हैं, लेकिन केवल अधिक शक्तिशाली एआरएम-आधारित प्रोसेसर (जो मैं एक तथ्य के लिए जानता हूं, उसमें C ++ कंपाइलर टूल-चेन हैं)।


59
मुझे एक प्रोजेक्ट के लिए C ++ का उपयोग करने के लिए जाना जाता है, केवल C फीचर्स का उपयोग करके, ताकि मैं //टिप्पणी कर सकूं। अगर यह काम करता है, तो क्यों नहीं?
जूल्स

76
जब आप सुविधाओं का अच्छा उपयोग नहीं करते हैं तो यह बुरा अभ्यास सी के लिए खुद को प्रतिबंधित कर देगा।
जेरी कॉफ़िन

35
जब आप कहते हैं कि "C ++ कंपाइलर का उपयोग करें" तो आपका मतलब है "C ++ का उपयोग करें"। मात्र यह कहें। आप C ++ कंपाइलर के साथ C को संकलित नहीं कर सकते हैं, लेकिन आप C से C ++ तक आसानी से स्विच कर सकते हैं, जो कि आप वास्तव में कर रहे हैं।
user253751

4
"मैं जो कर रहा हूं, उसके लिए प्रोसेसर पर कोई डायनेमिक मेमोरी एलोकेशन नहीं है और प्रोग्राम कुल मिलाकर काफी सरल है। यह उल्लेख नहीं करने के लिए कि डिवाइस में लगभग कोई प्रोसेसर पावर या संसाधन नहीं हैं। वास्तव में किसी भी C ++ का उपयोग करने की कोई मजबूत आवश्यकता नहीं है।" मुझे आशा है कि उन दो वाक्यों में से पहला C ++ का उपयोग न करने के कारण माना जाता है, क्योंकि वे बहुत बुरे हैं यदि वे हैं। C ++ एम्बेडेड सिस्टम के साथ उपयोग करने के लिए पूरी तरह से ठीक है।
फराप

21
@ जूल्स मुझे यकीन है कि आप यह जानते हैं और थोड़ी देर पहले सोच रहे थे, लेकिन अगर कोई इसे पढ़ रहा है तो: //C99 में C मानक में टिप्पणी नहीं की गई है।
डेविसलर

जवाबों:


77

मैं इतनी दूर नहीं जाऊंगा कि इसे "बुरा व्यवहार" कहूं , लेकिन न तो मुझे यकीन है कि यह वास्तव में आपकी समस्या का सही समाधान है। यदि आप चाहते हैं कि आपके चार डेटा प्रकारों को करने के लिए चार अलग-अलग कार्य हैं, तो सी प्रोग्रामर ने पुराने समय से क्या नहीं किया है:

void transmit_uchar_buffer(unsigned char *buffer);
void transmit_char_buffer(char *buffer);
void transmit_uchar(unsigned char c);
void transmit_char(char c);

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


8
मैं कहता हूं कि ऐसा क्यों नहीं है क्योंकि टाइप किया जा रहा है (शायद) एक कार्यान्वयन विवरण है, इसलिए इसे छिपाने और कार्यान्वयन का चयन करने के साथ संकलक सौदे को देने से अधिक पठनीय कोड हो सकता है। और अगर C ++ फीचर का उपयोग करने से पठनीयता में सुधार होता है, तो ऐसा क्यों नहीं?
जूल्स

29
एक भी कर सकते हैं #defineसंचारित () सी 11 का उपयोग कर_Generic
Deduplicator

16
@ जूल्स क्योंकि यह तब बहुत ही भ्रमित करने वाला है कि सी ++ सुविधाओं को परियोजना में उपयोग करने की अनुमति दी गई है। क्या कोई संभावित परिवर्तन जिसमें ऑब्जेक्ट अस्वीकृत हैं? टेम्पलेट्स के बारे में क्या? C ++ शैली टिप्पणियां? ज़रूर, आप एक कोडिंग शैली दस्तावेज़ के साथ उसके आसपास काम कर सकते हैं, लेकिन यदि आप सब कर रहे हैं तो फ़ंक्शन ओवरलोडिंग का एक सरल मामला है, तो बस इसके बजाय सी लिखें।
फिलिप केंडल

25
@Phillip "सी ++ शैली टिप्पणियाँ" एक दशक से अधिक समय के लिए वैध सी है।
डेविड कॉनरैड

12
@Jules: जबकि टाइप किया जा रहा है, संभवतः सॉफ़्टवेयर के लिए एक कार्यान्वयन विवरण है जो बीमा उद्धरण बनाता है, OPs एप्लिकेशन को सीरियल संचार करने वाला एक एम्बेडेड सिस्टम लगता है, जहां टाइप और डेटासेट महत्वपूर्ण महत्व है।
whatsisname

55

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

लिनक्स एक कोडबेस का एक उदाहरण है जहां लोग नियमित रूप से पूछते हैं कि पहचानकर्ता जैसे classनाम बदल दिए जाते हैं klassया kclass, ताकि वे लिनक्स को सी ++ कंपाइलर के साथ संकलित कर सकें। जाहिर है, सी ++ के लिनुस की राय को देखते हुए , वे हमेशा नीचे गोली मारते हैं : -डी जीसीसी एक कोडबेस का एक उदाहरण है जिसे पहले "सी ++ - क्लीन सी" में बदल दिया गया था, और फिर धीरे-धीरे अधिक सी ++ सुविधाओं का उपयोग करने के लिए फिर से तैयार किया गया।

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


15

आपकी दुविधा का एक वस्तुनिष्ठ उत्तर इस पर निर्भर करेगा:

  1. यदि आप C ++ का उपयोग करते हैं, तो निष्पादन योग्य का आकार काफी बढ़ जाता है।
  2. यदि आप C ++ का उपयोग करते हैं तो प्रदर्शन पर कोई ध्यान देने योग्य नकारात्मक प्रभाव पड़ता है।
  3. क्या कोड का पुन: उपयोग किसी अन्य प्लेटफ़ॉर्म पर किया जा सकता है जहाँ केवल C कंपाइलर उपलब्ध है।

यदि किसी भी प्रश्न का उत्तर "हां" है, तो आप अलग-अलग डेटा प्रकारों के लिए अलग-अलग नामित कार्यों को बनाने और सी के माध्यम से चिपके रहने से बेहतर हो सकते हैं।

यदि सभी प्रश्नों के उत्तर "नहीं" हैं, तो मुझे कोई कारण नहीं दिखता कि आपको C ++ का उपयोग क्यों नहीं करना चाहिए।


9
मुझे यह कहना चाहिए कि मैंने कभी भी C ++ कंपाइलर का सामना नहीं किया है जो दो भाषाओं के साझा सबसेट में लिखे गए कोड के लिए C कंपाइलर की तुलना में काफी खराब कोड उत्पन्न करता है। C ++ कंपाइलर्स को आकार और प्रदर्शन दोनों के लिए एक बुरा प्रतिनिधि मिलता है, लेकिन मेरा अनुभव है कि यह हमेशा C ++ सुविधाओं का अनुचित उपयोग है जो इस समस्या का कारण है ... विशेष रूप से, यदि आप आकार के बारे में चिंतित हैं, तो iostreams का उपयोग न करें और उपयोग न करें टेम्पलेट्स, लेकिन अन्यथा आप ठीक होना चाहिए।
जूल्स

@ जूल्स: बस इसके लायक क्या है (बहुत ज्यादा नहीं, आईएमओ) मैंने देखा है कि सी और सी ++ (टर्बो सी ++ 1.0 के लिए एक एकल संकलक के रूप में बेचा गया था, अगर स्मृति कार्य करता है) समान इनपुट के लिए काफी अलग परिणाम उत्पन्न करता है। जैसा कि मैं इसे समझता हूं, हालांकि, इससे पहले कि वे अपना सी ++ संकलक समाप्त कर लेते, इसलिए भले ही यह बाहर के एक संकलक की तरह दिखता था, लेकिन वास्तव में दो पूरी तरह से अलग संकलक थे - एक सी के लिए, दूसरा सी ++ के लिए।
जेरी कॉफ़िन

1
@ जेरीकॉफिन यदि स्मृति कार्य करती है, तो टर्बो उत्पादों की कभी भी बड़ी प्रतिष्ठा नहीं रही है। और अगर यह 1.0 संस्करण था, तो आपको अत्यधिक परिष्कृत नहीं होने के लिए बहाना किया जा सकता है। तो यह शायद बहुत प्रतिनिधि नहीं है।
बरमार

10
@ बरमार: वास्तव में, उनके पास काफी समय से काफी अच्छी प्रतिष्ठा थी। उनकी खराब प्रतिष्ठा अब मुख्य रूप से उनकी सरासर उम्र के कारण है। वे एक ही विंटेज के अन्य संकलक के साथ प्रतिस्पर्धा कर रहे हैं - लेकिन कोई भी सवाल नहीं करता है कि gcc 1.4 (या जो भी) के साथ चीजें कैसे करें। लेकिन आप सही हैं - यह बहुत प्रतिनिधि नहीं है।
जेरी कॉफिन

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

13

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

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

अपने उद्देश्य मानदंड के लिए,

  1. यदि आप C ++ का उपयोग करते हैं, तो निष्पादन योग्य का आकार काफी बढ़ जाता है।

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

  1. यदि आप C ++ का उपयोग करते हैं तो प्रदर्शन पर कोई ध्यान देने योग्य नकारात्मक प्रभाव पड़ता है।

मुझे संदेह है कि आप उस कोड के लिए ध्यान देने योग्य प्रदर्शन अंतर देखेंगे जिसे आप एक काल्पनिक शुद्ध-सी एनालॉग के रूप में वर्णित करते हैं।

  1. क्या कोड का पुन: उपयोग किसी अन्य प्लेटफ़ॉर्म पर किया जा सकता है जहाँ केवल C कंपाइलर उपलब्ध है।

मैं इस पर थोड़ा अलग प्रकाश डालूँगा: यदि आप उस कोड को लिंक करना चाहते हैं जिसे आप C ++ के साथ दूसरे कोड से लिंक कर रहे हैं , तो या तो उस कोड को C ++ में लिखना होगा और C ++ के साथ बनाया जाना होगा, या आपको इसकी आवश्यकता होगी अपने स्वयं के कोड में विशेष प्रावधान बनाने के लिए ("सी" लिंकेज घोषित करना), जो, इसके अतिरिक्त, आप अपने अतिभारित कार्यों के लिए बिल्कुल भी नहीं कर सकते हैं। दूसरी ओर, यदि आपका कोड C में लिखा और C के रूप में संकलित है, तो अन्य इसे C और C ++ दोनों मॉड्यूल से जोड़ सकते हैं। इस तरह की समस्या को आमतौर पर तालिकाओं को बदलकर दूर किया जा सकता है, लेकिन जब से आपको वास्तव में C ++ की आवश्यकता नहीं लगती है, तब पहली बार में इस तरह के मुद्दे को क्यों स्वीकार करें?


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

5

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

तब से, भाषाओं ने कुछ हद तक मोड़ दिया है।

mallocआपके सी कोड में हर एक प्रकार की बेमेल त्रुटि होगी - आपके मामले में कोई समस्या नहीं गतिशील स्मृति के साथ! इसी तरह, voidसी में आपके सभी संकेत आपको यात्रा करेंगे, क्योंकि आपको स्पष्ट जातियों को जोड़ना होगा। लेकिन ... आप इसे इस तरह से क्यों कर रहे हैं ... आपको सी ++ सुविधाओं का उपयोग करने के मार्ग का नेतृत्व किया जाएगा।

तो, यह कुछ अतिरिक्त काम के साथ संभव हो सकता है। लेकिन यह बड़े पैमाने पर C ++ गोद लेने के लिए एक प्रवेश द्वार के रूप में काम करेगा। कुछ वर्षों में लोग आपके विरासत कोड के बारे में शिकायत करेंगे, जो दिखता है कि यह 1989 में लिखा गया था, जैसा कि वे आपकी mallocकॉल को बदलते हैं new, लूप निकायों के कोड के ब्लॉक को केवल एक एल्गोरिथ्म को कॉल करने के लिए चीरते हैं, और असुरक्षित नकली बहुरूपता को तोड़ते हैं। तुच्छ किया गया है संकलक इसे करने की अनुमति दी गई थी।

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


2

कई प्रोग्रामिंग भाषाओं में एक या एक से अधिक संस्कृतियां होती हैं जो उनके आसपास विकसित होती हैं, और इस बारे में विशेष विचार होते हैं कि किसी भाषा को "होना" चाहिए। हालांकि, यह संभव होना चाहिए, व्यावहारिक और उपयोगी कम-स्तरीय भाषा के लिए सिस्टम प्रोग्रामिंग के लिए उपयुक्त है जो C ++ की कुछ विशेषताओं के साथ इस तरह के उद्देश्य के लिए उपयुक्त C की बोली को बढ़ाता है जो कि उपयुक्त होगा, दो भाषाओं के आसपास की संस्कृतियां। ' t ऐसे विलय का विशेष रूप से समर्थन करता है।

मैंने एक एम्बेडेड सी कंपाइलर के बारे में पढ़ा है जिसमें C ++ से कुछ विशेषताओं को शामिल किया गया है, जिसमें क्षमता भी शामिल है

foo.someFunction(a,b,c);

अनिवार्य रूप से व्याख्या की गई

typeOfFoo_someFunction(foo, a, b, c);

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

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


1
दिलचस्प राय है, लेकिन ओपी के सवाल को संबोधित नहीं करता है।
आर साहू

@RSahu: एक भाषा के आसपास "संस्कृति" को फिट करने वाला कोड बेहतर समर्थित होने के लिए उपयुक्त है और कोड की तुलना में विभिन्न प्रकार के कार्यान्वयन के लिए अधिक आसानी से अनुकूल है। सी और सी ++ की संस्कृतियां दोनों ओपी के सुझाव का उपयोग करती हैं, मैं विशिष्ट प्रश्नों के संबंध में कुछ और विशिष्ट बिंदुओं को जोड़ूंगा।
सुपरकाट

1
ध्यान दें कि C ++ मानक समिति में एक एम्बेडेड / वित्तीय / गेमिंग समूह है जो आपके द्वारा दावा की जाने वाली "छोटी रुचि" स्थितियों को हल करने के उद्देश्य से है।
याकूब

@ यक: मैं कबूल करूंगा कि मैं सी ++ दुनिया को बहुत करीब से नहीं देख रहा हूं, क्योंकि मेरे हित मुख्य रूप से सी के साथ हैं; मुझे पता है कि अधिक एम्बेडेड बोलियों की दिशा में प्रयास हुए हैं, लेकिन मैंने सोचा नहीं था कि वे वास्तव में कहीं भी मिलेंगे।
सुपरकैट

2

विचार करने के लिए एक अन्य महत्वपूर्ण कारक: जो कोई भी आपके कोड को इनहेरिट करेगा।

क्या वह व्यक्ति हमेशा C कंपाइलर के साथ C प्रोग्रामर बनने वाला है? मुझे ऐसा लगता है।

क्या वह व्यक्ति C ++ कंपाइलर वाला C ++ प्रोग्रामर भी होगा? मैं अपने कोड C ++ की विशिष्ट चीज़ों पर निर्भर होने से पहले इसके बारे में यथोचित रूप से सुनिश्चित होना चाहूंगा।


2

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

आपके मामले में यह कुछ ऐसा होगा

enum serialDataTypes
{
 INT =0,
 INT_P =1,
 ....
 }Arg_type_t;
....
....
void transmit(Arg_type_t serial_data_type, ...)
{
  va_list args;
  va_start(args, serial_data_type);

  switch(serial_data_type)
  {
    case INT: 
    //Send integer
    break;

    case INT_P:
    //Send data at integer pointer
    break;
    ...
   }
 va_end(args);
}

मुझे फिलिप्स का दृष्टिकोण पसंद है लेकिन यह आपके पुस्तकालय को बहुत सी कॉल के साथ प्रस्तुत करता है। ऊपर के साथ इंटरफ़ेस साफ है। इसकी कमियां हैं और अंततः यह अपनी पसंद का मामला है।


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

1

कुछ अलग-अलग प्रकारों के लिए "फ़ंक्शन" को ओवरलोड करने के आपके विशेष मामले के लिए, आप इसके _Genericमैक्रो मशीनरी के साथ C11 का उपयोग करने के बजाय विचार कर सकते हैं । मुझे लगता है कि यह आपकी सीमित जरूरतों के लिए पर्याप्त हो सकता है।

फिलिप केंडल के उत्तर का उपयोग करके आप परिभाषित कर सकते हैं:

#define transmit(X) _Generic((X),      \
   unsigned char*: transmit_uchar_buffer, \
   char*: transmit_char_buffer,           \
   unsigned char: transmit_uchar,         \
   char: transmit_char) ((X))

और transmit(foo) जो भी प्रकार हो foo(ऊपर सूचीबद्ध चार प्रकारों में से) कोड।

यदि आप केवल GCC (और संगत, उदा Clang ) संकलक के बारे में परवाह करते हैं , तो आप __builtin_types_compatible_pइसके typeofविस्तार पर विचार कर सकते हैं ।


1

क्या केवल फ़ंक्शन ओवरलोडिंग के लिए C ++ कंपाइलर का उपयोग करना बुरा है?

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

C साइड

C दृष्टिकोण से, मुझे लगता है कि आपके कोड को ओवरलोडिंग का उपयोग करने के लिए आपके कोड को C ++ की आवश्यकता होती है। जब तक आप इसे C ++ टेम्प्लेट के साथ स्थैतिक बहुरूपता के लिए उपयोग नहीं कर रहे हैं, यह ऐसी तुच्छ वाक्य रचना है, जो एक पूरी तरह से अलग भाषा में स्विच करने के बदले में प्राप्त की जाती है। इसके अलावा यदि आप कभी भी अपने कार्यों को एक dylib को निर्यात करना चाहते हैं (हो सकता है या एक व्यावहारिक चिंता नहीं हो सकती है), तो आप अब सभी नाम-रूपी प्रतीकों के साथ व्यापक खपत के लिए बहुत व्यावहारिक रूप से नहीं कर सकते हैं।

सी ++ साइड

C ++ के दृष्टिकोण से, आपको C ++ की तरह C का उपयोग फ़ंक्शन ओवरलोडिंग के साथ नहीं करना चाहिए। यह शैलीगत हठधर्मिता नहीं है, बल्कि रोजमर्रा के C ++ के व्यावहारिक उपयोग से संबंधित है।

सी कोड का आपका सामान्य प्रकार केवल यथोचित रूप से समझदार और "सुरक्षित" है यदि आप सी टाइप सिस्टम के खिलाफ काम कर रहे हैं जो कॉपी सीटर जैसी चीजों के लिए मना करता है structs। एक बार जब आप C ++ की अधिक समृद्ध प्रकार की प्रणाली में काम कर रहे होते हैं, तो दैनिक कार्य जो कि बहुत अधिक मूल्य के होते हैं memsetऔर memcpyवे कार्य नहीं बन जाते हैं जिन्हें आपको हर समय झुकना चाहिए। इसके बजाय, वे वे कार्य हैं जो आप आमतौर पर प्लेग की तरह से बचना चाहते हैं, चूंकि सी ++ प्रकार के साथ, आपको उन्हें कच्चे बिट्स और बाइट्स की तरह व्यवहार नहीं करना चाहिए और उन्हें कॉपी और फेरबदल किया जाना चाहिए और मुक्त किया जाना चाहिए। यहां तक ​​कि अगर आपका कोड इस समय केवल memsetआदिम और POD UDTs जैसी चीजों का उपयोग करता है , तब भी कोई भी आपके द्वारा उपयोग किए जाने वाले किसी भी UDT में एक Ctor जोड़ता है (केवल एक सदस्य को जोड़ने के लिए जिसे एक की आवश्यकता होती है, जैसेstd::unique_ptrसदस्य) इस तरह के कार्यों या एक आभासी फ़ंक्शन या उस तरह के कुछ के खिलाफ, यह आपके सभी सामान्य सी-स्टाइल कोडिंग को अपरिभाषित व्यवहार के लिए अतिसंवेदनशील बनाता है। इसे हर्ब सटर से लें:

memcpyऔर memcmpप्रकार प्रणाली का उल्लंघन। memcpyवस्तुओं की नकल करना फोटोकॉपीयर का उपयोग करके पैसा बनाने जैसा है। memcmpवस्तुओं की तुलना करने के लिए उपयोग करना अपने धब्बों को गिनकर तेंदुओं की तुलना करने जैसा है। उपकरण और विधियाँ कार्य करने के लिए प्रकट हो सकती हैं, लेकिन वे इसे स्वीकार करने के लिए बहुत मोटे हैं। C ++ ऑब्जेक्ट्स सभी जानकारी छिपाने के बारे में हैं (यकीनन सॉफ्टवेयर इंजीनियरिंग में सबसे लाभदायक सिद्धांत; आइटम 11 देखें): ऑब्जेक्ट डेटा छिपाते हैं (आइटम 41 देखें) और कंस्ट्रक्टर्स और असाइनमेंट ऑपरेटरों के माध्यम से उस डेटा को कॉपी करने के लिए सटीक सार को समर्पित करें (आइटम 52 से 55 तक देखें) । इन सबके साथ बुलडोज़िंग memcpyसूचना छिपाना का एक गंभीर उल्लंघन है, और अक्सर स्मृति और संसाधन लीक (सर्वोत्तम रूप से), क्रैश (बदतर), या अपरिभाषित व्यवहार (सबसे खराब) - सी ++ कोडिंग मानकों की ओर जाता है।

इतने सारे सी डेवलपर्स इससे सहमत नहीं हैं और ठीक ही इसलिए, क्योंकि दर्शन केवल तभी लागू होता है यदि आप C ++ में कोड लिख रहे हैं। आप सबसे अधिक संभावना कर रहे हैं कई समस्याएं खड़ी कोड लिखने अगर आप की तरह कार्यों का उपयोग memcpyहर समय कोड में सी ++ के रूप में बनाता है कि है, लेकिन यह पूरी तरह से ठीक है अगर आप यह कर सी में । टाइप सिस्टम में अंतर के कारण इस संबंध में दो भाषाएँ बहुत अलग हैं। यह बहुत ही आकर्षक है कि इन दोनों की विशेषताओं के सबसेट को देखना आम है और विश्वास है कि एक का उपयोग दूसरे की तरह किया जा सकता है, विशेष रूप से C ++ की तरफ, लेकिन C + कोड (या C-- कोड) आमतौर पर C और C दोनों की तुलना में कहीं अधिक समस्याग्रस्त है। C ++ कोड।

इसी तरह आप mallocसी-स्टाइल के संदर्भ में (जो कि कोई ईएच का मतलब नहीं है) का उपयोग नहीं करना चाहिए, अगर यह किसी भी सी ++ फ़ंक्शंस को सीधे कॉल कर सकता है, जो तब से आपके फ़ंक्शन में निहित निकास बिंदु के परिणामस्वरूप हो सकता है अपवाद जो आप प्रभावी ढंग से C- स्टाइल कोड लिखने से नहीं पकड़ सकते, freeउस मेमोरी में सक्षम होने से पहले । तो जब भी आप सी के रूप में एक साथ ++ बनाता है कि एक फ़ाइल .cppएक्सटेंशन या जो कुछ भी है और यह जैसी चीजों के इन सभी प्रकार करता है malloc, memcpy, memset,qsort, आदि, तो यह लाइन के आगे समस्याओं के लिए पूछ रहा है यदि पहले से ही नहीं है जब तक कि यह एक वर्ग का कार्यान्वयन विवरण नहीं है जो केवल आदिम प्रकारों के साथ काम करता है, जिस बिंदु पर यह अभी भी अपवाद-सुरक्षित होने के लिए अपवाद-हैंडलिंग करने की आवश्यकता है। आप सी ++ कोड लिख रहे हैं आप के बजाय आम तौर पर आरए II पर भरोसा करते हैं और तरह बातें उपयोग करना चाहते हैं vector, unique_ptr, shared_ptr, आदि, और जब संभव हो सभी सामान्य सी-शैली कोडिंग से बचें।

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

अपवाद-सुरक्षा

फिर, जिस क्षण आप C ++ भूमि में होते हैं, लोग आपके कोड को अपवाद-सुरक्षित होने की उम्मीद करने जा रहे हैं। लोग आपके कोड को भविष्य में बनाए रख सकते हैं, यह देखते हुए कि यह पहले से ही C ++ में लिखा और संकलित है, और बस std::vector, dynamic_cast, unique_ptr, shared_ptrकोड में आदि का उपयोग करते हैं , जिसे आपके कोड द्वारा प्रत्यक्ष या अप्रत्यक्ष रूप से कहा जाता है, यह मानते हुए कि आपका कोड पहले से ही "C ++" है। कोड। उस बिंदु पर हमें उस मौके का सामना करना होगा जो चीजें फेंक देंगे, और फिर जब आप इस तरह पूरी तरह से ठीक और प्यारा सी कोड लेंगे:

int some_func(int n, ...)
{
    int* x = calloc(n, sizeof(int));
    if (x)
    {
        f(n, x); // some function which, now being a C++ function, may 
                 // throw today or in the future.
        ...
        free(x);
        return success;
    }
    return fail;
}

... अब टूट गया है। अपवाद-सुरक्षित होने के लिए इसे फिर से लिखना होगा:

int some_func(int n, ...)
{
    int* x = calloc(n, sizeof(int));
    if (x)
    {
        try
        {
            f(n, x); // some function which, now being a C++ function, may 
                     // throw today or in the future (maybe someone used
                     // std::vector inside of it).
        }
        catch (...)
        {
            free(x);
            throw;
        }
        ...
        free(x);
        return success;
    }
    return fail;
}

कुल! यही कारण है कि ज्यादातर सी ++ डेवलपर्स इसके बजाय यह मांग करेंगे:

void some_func(int n, ...)
{
    vector<int> x(n);
    f(x); // some function which, now being a C++ function, may throw today
          // or in the future.
}

उपरोक्त RAII-अनुरूप अपवाद-सुरक्षित कोड है जो C ++ डेवलपर्स आमतौर पर स्वीकृत करेगा क्योंकि फ़ंक्शन लीक नहीं करेगा, जिसके परिणामस्वरूप कोड की कौन सी पंक्ति ट्रिगर नहीं होती है, जिसके परिणामस्वरूप throw

एक भाषा चुनें

आपको या तो RAII, अपवाद-सुरक्षा, टेम्प्लेट, OOP, आदि के साथ C ++ के टाइप सिस्टम और दर्शन को गले लगाना चाहिए या C को गले लगाना चाहिए जो मोटे तौर पर कच्चे बिट्स और बाइट्स के आसपास घूमता है। आपको इन दो भाषाओं के बीच एक अपवित्र विवाह नहीं करना चाहिए, और उन्हें अलग-अलग भाषाओं में अलग-अलग करने के बजाय उन्हें एक साथ धुंधला करने के लिए अलग-अलग व्यवहार करना चाहिए।

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

बाइनरी आकार

जिज्ञासा से बाहर मैंने अपनी मुफ्त सूची के कार्यान्वयन और बेंचमार्क को अभी लेने की कोशिश की और इसे सी ++ में पोर्ट किया क्योंकि जब से मैं वास्तव में इसके लिए उत्सुक हुआ:

[...] पता नहीं है कि यह सी के लिए कैसा लगेगा क्योंकि मैं सी कंपाइलर का उपयोग नहीं कर रहा हूं।

... और जानना चाहता था कि क्या बाइनरी आकार C ++ के रूप में सभी इमारत में बढ़ेगा। इसने मुझे सभी जगहों पर स्पष्ट जातियों को छिड़कने की आवश्यकता थी, जो वास्तव में एक कारण था (एक कारण मुझे वास्तव में सी में बेहतर स्तर के आवंटन और डेटा संरचना जैसी चीजें लिखना पसंद था) लेकिन केवल एक मिनट लगा।

सिर्फ सी के साथ यह निर्माण और, का उपयोग करते हुए कहते हैं के बीच का अंतर, - यह सिर्फ एक सरल सांत्वना अनुप्रयोग के लिए और कोड है कि किसी भी सी ++ सुविधाओं, यहां तक कि नहीं ऑपरेटर ओवरलोडिंग का प्रयोग नहीं करते एक MSVC 64-बिट रिलीज निर्माण की तुलना की गई थी <cstdlib>के बजाय <stdlib.h>और इस तरह की चीजें, लेकिन मुझे यह जानकर आश्चर्य हुआ कि यह द्विआधारी आकार में शून्य अंतर था!

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

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.