मुझे ऐसे कार्य कहां करने चाहिए जो किसी वर्ग से संबंधित नहीं हैं?


47

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

उन्हें लगाने के लिए सबसे अच्छी जगह कहां है? मान लें कि मेरे पास यह है:

class A{
    public:
        int math_function1(int);
        ...
}

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

इस स्थिति में अच्छा अभ्यास क्या है? अभी मैं उन्हें नई कक्षाओं में कॉपी-पेस्ट कर रहा हूं, जो मुझे यकीन है कि सबसे खराब अभ्यास है।


11
क्या आपने staticकीवर्ड के बारे में सीखा है ?
S.Lott

30
C ++ में, फ्री फ़ंक्शंस लगभग हमेशा सदस्य फ़ंक्शंस पर पसंद किए जाते हैं।
Pubby

4
ऐसा कोई नियम नहीं है जो कहता है कि सब कुछ एक वर्ग में होना है। कम से कम C ++ में नहीं।
tdammers

2
मैं स्थैतिक विधियों का एक समूह के साथ एक वर्ग के लिए एक नाम स्थान पसंद करूंगा
निक कीघी

जवाबों:


70

C ++ में गैर-विधि फ़ंक्शन ठीक हो सकते हैं, यदि वे एक वर्ग के नहीं हैं, तो उन्हें एक कक्षा में न रखें, बस उन्हें वैश्विक या अन्य नाम स्थान के दायरे में रखें

namespace special_math_functions //optional
{
    int math_function1(int arg)
    {
         //definition 
    }
}

6
+1 यह सबसे समझदार समाधान है, हालांकि अतिरिक्त नाम स्थान आवश्यक नहीं लगता है।
पब

1
नहीं, यह आवश्यक नहीं है
जे.के.

27
कुछ नामस्थान अन्य पुस्तकालयों के साथ संभावित नाम टकराव को कम करने के लिए उपयोगी है।
बिल डोर

11
नेमस्पेस का उपयोग करना भी अच्छा है क्योंकि यह स्पष्ट करता है कि कॉल एक विधि है या फ़ंक्शन है। ( math_function1(42)वर्तमान वर्ग के सदस्य को special_math_functions::math_function1(42)बुला सकता है ; स्पष्ट रूप से एक स्वतंत्र कार्य कह रहा है)। कहा जा रहा है, ::math_function(42)एक ही छूट प्रदान करता है।
०१

2
नाम स्थान आवश्यक नहीं हैं, लेकिन वे निषिद्ध भी नहीं हैं। इसलिए यह उत्तर क्यों कहता है // optional। स्वादानुसार सीज़न।
user253751

6

इस बात पर निर्भर करता है कि परियोजना कैसे व्यवस्थित है और आप किस तरह के डिज़ाइन पैटर्न का उपयोग कर रहे हैं, यह मानते हुए कि यह सख्ती से उपयोगिता कोड है, आपके पास निम्न विकल्प हैं:

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

ध्यान दें कि पहला विकल्प सबसे अच्छा दांव होने जा रहा है और निम्नलिखित तीन सीमित उपयोगिता वाले हैं। हालांकि, आपने कहा कि आपका सामना तब हो सकता है, जब सी # या जावा प्रोग्रामर कुछ सी ++ काम कर रहे हों या यदि आप कभी भी सी # या जावा कोड पर काम करते हैं, जहां कक्षाओं का उपयोग अनिवार्य है।


क्यों डाउन वोट?
rjzii

10
मैं नीच नहीं हूं, लेकिन शायद इसलिए कि आप स्थिर कार्यों या एक सिंगलटन के साथ एक वर्ग की सलाह दे रहे हैं, जबकि मुक्त कार्य संभवतः इस मामले में ठीक होंगे (और सी ++ में कई चीजों के लिए स्वीकार्य और उपयोगी हैं)।
एंटोन गोलोव

@AntonGolov - निशुल्क कार्य पहली चीज है जिसका मैंने सूची में उल्लेख किया है। :) उनमें से बाकी उन स्थितियों के लिए अधिक ओओपी उन्मुख दृष्टिकोण हैं जहां आप "सब कुछ एक वर्ग होना चाहिए!" वातावरण।
rjzii

9
@Rob Z: हालाँकि, C ++ उनमें से एक नहीं है "सब कुछ एक वर्ग होना चाहिए!" वातावरण।
डेविड थॉर्नले

1
कब से यह OOP शुद्ध कार्यों को एक वर्ग में मजबूर करने के लिए है? OOP-कार्गो-पंथ की तरह लगता है।
डिडुप्लीकेटर

1

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

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

उदाहरण के लिए नेट में, जैसी बातों Min()और Max()पर स्थिर सदस्यों के रूप में प्रदान की जाती हैं System.Mathवर्ग

यदि आपके सभी कार्य गणित से संबंधित हैं और आप अन्य लोगों के पास एक विशाल Mathवर्ग होगा, तो आप इसे आगे तोड़ना चाहेंगे और कक्षाओं को पसंद कर सकते हैं TrigonometryUtilities, EucledianGeometryUtilitiesऔर इसी तरह।

एक अन्य विकल्प यह होगा कि साझा कार्यक्षमता को उन वर्गों के आधार वर्ग में रखा जाए, जिन्हें कार्यक्षमता की आवश्यकता है। यह अच्छी तरह से काम करता है, जब प्रश्नों में कार्यों को उदाहरण के डेटा पर संचालित करने की आवश्यकता होती है, हालांकि, यह दृष्टिकोण भी कम लचीला है यदि आप कई विरासत से बचना चाहते हैं और केवल एक आधार वर्ग से चिपके रहते हैं, क्योंकि आप अपने एक आधार का "उपयोग" कर रहे होंगे बस कुछ साझा कार्यक्षमता तक पहुँच पाने के लिए वर्ग।


18
IMHO, कुछ भी नहीं है, लेकिन स्थिर सदस्यों के साथ उपयोगिता वर्ग C ++ में एक विरोधी पैटर्न है। आप एक नेमस्पेस के व्यवहार को पूरी तरह से पुन: पेश करने के लिए एक वर्ग का उपयोग कर रहे हैं, जो वास्तव में कोई मतलब नहीं है।
21

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

5
@ S.Robins: C ++ में ऐसा कुछ भी करने की आवश्यकता नहीं है, आप उन्हें केवल एक नाम स्थान में रख सकते हैं, जिसका सटीक समान प्रभाव है।
डेडएमजी

0

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

// a general helper 
template <class T>
bool isPrinter(T& p){
   return (dynamic_cast<Printer>(p))? true: false;
}

    // specific helper for printers
namespace printer_utils {    
  namespace HP {
     print_alignment_page() { printAlignPage();}
  }

  namespace Xerox {
     print_alignment_page() { Alignment_Page_Print();}
  }

  namespace Canon {
     print_alignment_page() { AlignPage();}
  }

   namespace Kyocera {
     print_alignment_page() { Align(137,4);}
   }

   namespace Panasonic {
      print_alignment_page() { exec(0xFF03); }
   }
} //namespace

अब isPrinterइसके हेडर सहित किसी भी कोड के लिए उपलब्ध है, लेकिन print_alignment_pageएक using namespace printer_utils::Xerox;निर्देश की आवश्यकता है । कोई भी इसे संदर्भित कर सकता है

Canon::print_alignment_page();

अधिक स्पष्ट होना।

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

वास्तव में, using namespace std;हेडर फ़ाइल में उपयोग करने की अनुशंसा नहीं की जाती है या, जैसा कि अक्सर किया जाता है, अंदर की पहली पंक्ति के रूप में main()std::5 पत्र है और अक्सर (विशेष रूप से उपयोग करने के लिए समारोह चाहता प्रस्तावना के लिए एक घर का काम लगता है std::coutऔर std::endl!) लेकिन यह एक उद्देश्य पूरा करता है।

नई C ++ 11 में कुछ उप-नामस्थान हैं जैसे कि विशेष सेवाओं के लिए

std::placeholders,
std::string_literals,
std::chrono,
std::this_thread,
std::regex_constants

जिसे उपयोग के लिए लाया जा सकता है।

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

#include <iostream>
#include <string>
#include <vector>

namespace Needed {
  using std::vector;
  using std::string;
  using std::cout;
  using std::endl;
}

int main(int argc, char* argv[])
{
  /*  using namespace std; */
      // would avoid all these individual using clauses,
      // but this way only these are included in the global
      // namespace.

 using namespace Needed;  // pulls in the composition

 vector<string> str_vec;

 string s("Now I have the namespace(s) I need,");

 string t("But not the ones I don't.");

 str_vec.push_back(s);
 str_vec.push_back(t);

 cout << s << "\n" << t << endl;
 // ...

यह तकनीक संपूर्ण के लिए जोखिम को सीमित करती है std:: namespace( यह बड़ा है! ) और किसी को सबसे आम कोड लाइनों के लिए क्लीनर कोड लिखने की अनुमति देता है जो लोग सबसे अधिक बार लिखते हैं।


-2

आप इसे विभिन्न प्रकार के पूर्णांकों और / या फ़्लोट्स के लिए उपलब्ध कराने के लिए इसे टेम्प्लेट फ़ंक्शन में रखना चाह सकते हैं:

template <typename T>
T math_function1(T){
 ..
}

आप स्वच्छ कस्टम प्रकार भी बना सकते हैं जो उदाहरण के लिए प्रतिनिधित्व करते हैं बड़ी संख्या या जटिल संख्या आपके कस्टम प्रकार के लिए प्रासंगिक ऑपरेटरों को ओवरलोड करके उन्हें टेम्पलेट के अनुकूल बनाते हैं।

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