ক্লাসের সাথে সম্পর্কিত নয় এমন ফাংশনগুলি কোথায় রাখব?


47

আমি একটি সি ++ প্রকল্পে কাজ করছি যেখানে আমার কাছে একগুচ্ছ গণিত ফাংশন রয়েছে যা আমি প্রথমে ক্লাসের অংশ হিসাবে ব্যবহার করার জন্য লিখেছিলাম। আমি আরও কোড লিখছি যেহেতু, আমি বুঝতে পেরেছি যে আমার সর্বত্র এই গণিতের ফাংশন প্রয়োজন need

এগুলি রাখার সবচেয়ে ভাল জায়গা কোথায়? ধরা যাক আমার কাছে এটি রয়েছে:

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

(কিভাবে বা leat এ আমি জানি না) ব্যবহারের যে আর যখন আমি আরেক শ্রেণী লিখুন, আমি পারবো না math_function1যে অন্যান্য ক্লাসে। এছাড়াও, আমি বুঝতে পেরেছি যে এগুলির কয়েকটি ফাংশন সত্যই ক্লাস এ এর ​​সাথে সম্পর্কিত নয় They এগুলি শুরুতে মনে হয়েছিল, তবে এখন আমি দেখতে পাচ্ছি তারা কীভাবে গণিতের কাজ।

এই পরিস্থিতিতে ভাল অনুশীলন কি? এই মুহুর্তে আমি তাদের নতুন ক্লাসে কপি-পেস্ট করেছি, যা আমি নিশ্চিত যে সবচেয়ে খারাপ অভ্যাস।


11
আপনি staticকীওয়ার্ড সম্পর্কে শিখেছেন ?
এস। লট

30
সি ++ এ, ফ্রি ফাংশনগুলি প্রায়শই সদস্য ফাংশনের চেয়ে বেশি পছন্দ করা হয়।
পাব্বি

4
এমন কোনও নিয়ম নেই যা বলে যে সবকিছুই একটি শ্রেণিতে থাকতে হবে। কমপক্ষে সি ++ তে নেই।
টিডামাররা

2
আমি স্থির পদ্ধতিগুলির একগুচ্ছ সহ একটি শ্রেণীর জন্য একটি নেমস্পেস পছন্দ করতাম
নিক কেইগলি

উত্তর:


70

সি ++ এর নন-মেথড ফাংশনগুলি ঠিকঠাক থাকতে পারে, যদি তারা কোনও শ্রেণীর অন্তর্ভুক্ত না হয় তবে সেগুলি কোনও শ্রেণিতে রাখে না, কেবল তাদের বিশ্বব্যাপী বা অন্য নামের জায়গাগুলিতে রাখুন them

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

6
+1 এটি সর্বাধিক বুদ্ধিমান সমাধান, যদিও অতিরিক্ত নেমস্পেসের প্রয়োজনীয় মনে হয় না।
পাব্বি

1
না এটি প্রয়োজনীয় নয়
জে কে।

27
অন্যান্য গ্রন্থাগারের সাথে সম্ভাব্য নামের সংঘর্ষ হ্রাস করতে কিছু নামস্থান কার্যকর।
বিল ডোর 21

11
নেমস্পেসটি ব্যবহার করাও দুর্দান্ত কারণ এটি কলটি কোনও পদ্ধতি বা কোনও ফাংশন কিনা তা ছত্রভঙ্গ করে। ( math_function1(42)বর্তমান বর্গের কোনও সদস্যকে কল করতে পারে; special_math_functions::math_function1(42)স্পষ্টভাবে একটি স্বাধীন ফাংশন কল করছে)। বলা হচ্ছে, ::math_function(42)একই অনর্থক উপলব্ধ করা হয়।
ipet

2
নেমস্পেসগুলি প্রয়োজনীয় নয় তবে সেগুলি নিষিদ্ধও নয়। সুতরাং কেন এই উত্তর বলে // optional। স্বাদ অনুযায়ী মরসুম।
ব্যবহারকারী 253751

6

প্রকল্পটি কীভাবে সংগঠিত হয়েছে এবং কী ধরণের ডিজাইনের ধরণগুলি আপনি ব্যবহার করছেন তা নির্ভর করে, ধরে নিচ্ছেন এটি আপনার নিম্নলিখিত বিকল্পগুলি কঠোরভাবে ইউটিলিটি কোড হিসাবে গ্রহণ করেছেন:

  • আপনার যদি সমস্ত কিছুর জন্য অবজেক্ট ব্যবহার না করতে হয় তবে আপনি কিছু সহজ করতে পারেন যেমন তাদের চারপাশে কোনও ক্লাসের মোড়ক ছাড়াই একটি ফাইলের মধ্যে রাখুন। ভবিষ্যতে কোনও সমস্যা রোধ করার জন্য নেমস্পেসের সুপারিশ করা হলেও এটি কোনও নেমস্পেসের সাথে বা ছাড়াই থাকতে পারে।
  • পরিচালিত সি ++ এর জন্য আপনি সেগুলি ধারণের জন্য একটি স্ট্যাটিক বর্গ তৈরি করতে পারেন ; তবে এটি সত্যিকারের শ্রেণীর মতোই কাজ করে না এবং আমার বোধগম্যতা এটি একটি সি ++ অ্যান্টি-প্যাটার্ন।
  • আপনি যদি পরিচালিত সি ++ ব্যবহার না করে থাকেন তবে সেগুলিতে অ্যাক্সেস করার অনুমতি দেওয়ার জন্য আপনি কেবল স্ট্যাটিক ফাংশন ব্যবহার করতে পারেন এবং সেগুলি সমস্ত একক শ্রেণিতে অন্তর্ভুক্ত রাখতে পারেন। এটি কার্যকর হতে পারে যদি এমন অন্যান্য ক্রিয়াকলাপও রয়েছে যেগুলির জন্য আপনি একটি উপযুক্ত তাত্ক্ষণিক বস্তুটি চান এটি একটি অ্যান্টি-প্যাটার্নও হতে পারে।
  • আপনি যদি নিশ্চিত করতে চান যে ফাংশনগুলি সম্বলিত অবজেক্টের কেবলমাত্র একটি উদাহরণ উপস্থিত থাকবে তবে আপনি কোনও ইউটিলিটি ক্লাসের জন্য সিঙ্গলটন প্যাটার্ন ব্যবহার করতে পারেন যা আপনাকে ভবিষ্যতে কিছুটা নমনীয়তাও দেয় কারণ আপনি এখন অ স্থিত বৈশিষ্ট্যের অ্যাক্সেস পেয়েছেন। এটি সীমিত ব্যবহারের হতে চলেছে এবং যদি আপনার কোনও কারণে কোনও কারণের প্রয়োজন হয় তবেই এটি সত্যিই প্রযোজ্য। প্রতিক্রিয়াগুলি হ'ল যদি আপনি এটি করেন তবে আপনি কেন ইতিমধ্যে তা জানতে পারবেন।

মনে রাখবেন যে প্রথম বিকল্পটি সেরা বাজি হতে চলেছে এবং নিম্নলিখিত তিনটিই সীমিত উপযোগী। যদিও এটি বলেছে, আপনার মুখোমুখি হতে পারে কেবল সি # বা জাভা প্রোগ্রামাররা কিছু সি ++ কাজ করার কারণে বা যদি আপনি সি # বা জাভা কোডে যেখানে ক্লাস ব্যবহার বাধ্যতামূলক হয় তখনও কাজ করেন।


ডাউন-ভোট কেন?
rjzii

10
আমি ডাউনভোটার নই, তবে সম্ভবত আপনি স্ট্যাটিক ফাংশন বা সিঙ্গলটনের সাথে ক্লাসের পরামর্শ দিচ্ছেন, তবে ফ্রি ফাংশনগুলি সম্ভবত এই ক্ষেত্রে ভাল হবে (এবং সি ++ এর অনেক কিছুর জন্য গ্রহণযোগ্য এবং দরকারী)।
আন্তন গোলভ

@ অ্যান্টনগোলভ - ফ্রি ফাংশনগুলি হ'ল আমি তালিকায় প্রথম উল্লেখ করেছি। :) এর মধ্যে বাকিগুলি হ'ল পরিস্থিতিগুলির জন্য আরও ওওপিএরপিডেড পন্থাগুলি যেখানে আপনি "সমস্ত কিছু অবশ্যই একটি শ্রেণি হতে হবে!" পরিবেশের।
rjzii

9
@ রব জেড: তবে, সি ++ এর মধ্যে একটি নয় "" সবকিছু অবশ্যই একটি শ্রেণি হতে হবে! " পরিবেশের।
ডেভিড থর্নলি

1
কখন থেকে ক্লাসে বিশুদ্ধ ফাংশন জোর করা ওওপি হয়? OOP-cargo-cult এর মতো আরও মনে হচ্ছে।
উত্সাহক

1

যেমনটি আপনি ইতিমধ্যে বলেছিলেন, কোডটি অনুলিপি করা কোডটি পুনরায় ব্যবহারের সবচেয়ে খারাপ রূপ। আপনার যদি এমন কোনও ফাংশন থাকে যা আপনার কোনও শ্রেণীর সাথে সম্পর্কিত নয় বা বিভিন্ন পরিস্থিতিতে ব্যবহার করা যেতে পারে তবে সেগুলি দেওয়ার সর্বোত্তম জায়গা হেল্পার বা ইউটিলিটি ক্লাস। যদি তারা কোনও উদাহরণ ডেটা ব্যবহার না করে তবে এগুলি স্থিতিশীল করা যায়, তাই এটি ব্যবহারের জন্য আপনাকে ইউটিলিটি ক্লাসের কোনও উদাহরণ তৈরি করার দরকার নেই।

দেখুন এখানে নেটিভ C ++ স্ট্যাটিক সদস্য ফাংশন আলোচনার জন্য এবং এখানে পরিচালিত C ++ স্ট্যাটিক ক্লাস জন্য। তারপরে আপনি এই কোডটি ক্লাস করতে যেখানেই আপনার কোডটি আটকে দিয়েছিলেন।

উদাহরণস্বরূপ .NET সালে ভালো জিনিস Min()এবং Max()উপর স্ট্যাটিক সদস্য হিসেবে প্রদান করা হয় System.Mathবর্গ

আপনার সব ফাংশন গণিত সংক্রান্ত এবং আপনি otherwiese একটি রাক্ষুসে আছে তাহলে Mathবর্গ, আপনি আরও এটি ডাউন বিরতি এবং মত ক্লাস আছে চাইবেন TrigonometryUtilities, EucledianGeometryUtilitiesইত্যাদি।

আরেকটি বিকল্প হ'ল ভাগ্য কার্যকারিতা ক্লাসের একটি বেস শ্রেণীর মধ্যে বলা কার্যকারিতা প্রয়োজন। এটি ভালভাবে কাজ করে, যখন প্রশ্নগুলির ফাংশনগুলিতে উদাহরণস্বরূপ ডেটা পরিচালনা করতে হবে তবে আপনি যদি একাধিক উত্তরাধিকার এড়াতে চান এবং কেবল একটি বেস শ্রেণিতে আটকে থাকতে চান তবে এই পদ্ধতিটিও কম নমনীয় হবে কারণ আপনি আপনার এক ভিত্তিকে "ব্যবহার" করছেন ক্লাসে কিছু অংশীদারি কার্যকারিতা অ্যাক্সেস পেতে।


18
আইএমএইচও, স্ট্যাটিক সদস্য ব্যতীত ইউটিলিটি ক্লাসগুলি সি ++ এ অ্যান্টি-প্যাটার্ন। আপনি একটি স্থান ব্যবহার করে যাচ্ছেন এমন একটি স্থানের আচরণের পুরোপুরি পুনরুত্পাদন করতে, যা সত্যিকার অর্থে কোনও অর্থে আসে না।
ipet

ইউটিলিটি ক্লাস উল্লেখ করার জন্য +1। সি # এর মতো ভাষাগুলির জন্য একটি ক্লাসে থাকা সমস্ত কিছু প্রয়োজন তাই বিভিন্ন উদ্দেশ্যে বিভিন্ন সংখ্যক ইউটিলিটি ক্লাস তৈরি করা বেশ সাধারণ। স্ট্যাটিক হিসাবে এই শ্রেণিগুলি প্রয়োগ করা ইউটিলিটিগুলিকে আরও বেশি ব্যবহারকারী বান্ধব করে তোলে এবং উত্তরাধিকারসূত্রে কখনও কখনও তৈরি হতে পারে এমন মাথাব্যাথা এড়ানো হয়, বিশেষত যখন বেস শ্রেণিগুলি কোড দিয়ে স্ফীত হয়ে যায় যা কেবলমাত্র এক বা দুটি বংশধর দ্বারা ব্যবহৃত হতে পারে। আপনার ইউটিলিটি ফাংশনগুলিকে বৈশ্বিক পরিমন্ডলে ভাসমান না রেখে বরং আপনার ইউটিলিটি ফাংশনের জন্য অর্থবহ প্রসঙ্গ সরবরাহ করতে অনুরূপ কৌশলগুলি অন্যান্য ভাষায় প্রয়োগ করা যেতে পারে।
এস। রবিন্স

5
@ এস রবিনস: সি ++ তে এর মতো কোনও কিছুর প্রয়োজন নেই, আপনি কেবল এটিকে একটি নেমস্পেসে রাখতে পারেন, যার সঠিক একই প্রভাব রয়েছে।
ডেড এমএমজি

0

"সহায়ক ফাংশন" শব্দটি বাতিল করুন। একটি সংজ্ঞা একটি সুবিধাজনক ফাংশন যা আপনি কিছু কাজ করার জন্য সর্বদা ব্যবহার করেন। এগুলি মূল নেমস্পেসে থাকতে পারে এবং তাদের নিজস্ব শিরোনাম ইত্যাদি থাকতে পারে help অন্যান্য সহায়ক ফাংশন সংজ্ঞাটি একটি একক শ্রেণি বা শ্রেণি পরিবারের জন্য একটি ইউটিলিটি ফাংশন।

// 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!) তার উপস্থাপিত করার কাজটি বেশিরভাগ সময় মনে হয় তবে এটি কোনও উদ্দেশ্য করে।

নতুন সি ++ 11 এর মধ্যে বিশেষ পরিষেবাদির জন্য কিছু উপ-নামস্থান রয়েছে sub

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){
 ..
}

আপনি ঝরঝরে কাস্টম প্রকারগুলি তৈরি করতে পারেন যা উদাহরণস্বরূপ বিশাল সংখ্যা বা জটিল সংখ্যার জন্য আপনার কাস্টম প্রকারের জন্য প্রাসঙ্গিক অপারেটরগুলিকে ওভারলোড করে তাদের টেমপ্লেটিকে বন্ধুত্বপূর্ণ করে তোলে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.