c++ - অবজ - সি++ প্রোগ্রামিং বই ডাউনলোড




কখন আপনি সি++ এ 'বন্ধুর' ব্যবহার করবেন? (20)

আমি সি ++ এফএকিউ এর মাধ্যমে পড়তেছি এবং friend ঘোষণার বিষয়ে অদ্ভুত ছিলাম। আমি ব্যক্তিগতভাবে এটি ব্যবহার করা হয়নি, তবে আমি ভাষা অনুসন্ধান করতে আগ্রহী।

friend ব্যবহার করার একটি ভাল উদাহরণ কি?

প্রায়শই জিজ্ঞাসা করা প্রশ্নাবলীটি একটু বেশি << >> অপারেটর ওভারলোডিং এবং সেই ক্লাসগুলির বন্ধু হিসেবে যুক্ত করার ধারণাটি পছন্দ করি। তবে আমি কিভাবে encapsulation বিরতি না নিশ্চিত না। কখন এই ব্যতিক্রমগুলি OOP এর কঠোরতার মধ্যে থাকতে পারে?


TDD অনেক বার করতে আমি C ++ এ 'বন্ধুর' শব্দটি ব্যবহার করেছি।
একজন বন্ধু আমার সম্পর্কে সবকিছু জানেন?

না, এর একমাত্র উপায় বন্ধুত্ব: `(


সম্পাদন: একটু বেশি প্রশ্ন পড়া << >> অপারেটর ওভারলোডিং এবং সেই ক্লাসগুলির বন্ধু হিসাবে যুক্ত করার ধারণাটি আমি পছন্দ করি, তবে আমি নিশ্চিত নই যে এটি কীভাবে এনক্যাপুলেশন ভাঙ্গবে না

কিভাবে encapsulation বিরতি হবে?

যখন আপনি একটি ডেটা সদস্যকে অননুমোদিত অ্যাক্সেসের অনুমতি দেন তখন আপনি ইনકેપসুলেশনটি ভাঙ্গেন। নিম্নলিখিত ক্লাস বিবেচনা করুন:

class c1 {
public:
  int x;
};

class c2 {
public:
  int foo();
private:
  int x;
};

class c3 {
  friend int foo();
private:
  int x;
};

c1 স্পষ্টভাবে encapsulated হয় না। যে কেউ এটি পড়তে এবং x পরিবর্তন করতে পারেন। আমাদের কোনও অ্যাক্সেস নিয়ন্ত্রণ প্রয়োগ করার কোন উপায় নেই।

c2 স্পষ্টভাবে encapsulated হয়। x পাবলিক এক্সেস নেই। আপনি যা করতে পারেন তা হল foo ফাংশন কল করুন যা ক্লাসে কিছু অর্থপূর্ণ ক্রিয়াকলাপ সম্পাদন করে।

c3 ? যে কম encapsulated হয়? এটা কি x থেকে নিষিদ্ধ অ্যাক্সেস অনুমতি দেয়? এটা অজানা ফাংশন অ্যাক্সেস অনুমতি দেয়?

না। এটা অবিকল এক ফাংশন ক্লাসের ব্যক্তিগত সদস্যদের অ্যাক্সেস করার অনুমতি দেয়। শুধু c2 মত। এবং c2 মতো, অ্যাক্সেসের একটি ফাংশন "কিছু র্যান্ডম, অজানা ফাংশন" নয়, তবে "বর্গ সংজ্ঞাতে তালিকাভুক্ত ফাংশন"। শুধু c2 মতো, আমরা দেখতে পারি, ক্লাসের সংজ্ঞাগুলি দেখতে কেবলমাত্র অ্যাক্সেসের সম্পূর্ণ তালিকা রয়েছে।

সুতরাং কিভাবে এই কম encapsulated হয়? কোডের একই পরিমাণে ক্লাসের ব্যক্তিগত সদস্যদের অ্যাক্সেস আছে। এবং অ্যাক্সেস আছে প্রত্যেকের বর্গ সংজ্ঞা তালিকাভুক্ত করা হয়।

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

প্রথম, ইতিমধ্যে দেখানো হিসাবে, এটা খুব সীমিত। বন্ধুর পদ্ধতিগুলি একইভাবে করার অনুমতি দেওয়া উচিত নয় এমন কোনো কারণ নেই।

দ্বিতীয়ত, এটি যথেষ্ট সীমাবদ্ধ নয়। চতুর্থ শ্রেণী বিবেচনা করুন:

class c4 {
public:
  int getx();
  void setx(int x);
private:
  int x;
};

এই, উপরের জাভা মানসিকতা অনুযায়ী, পুরোপুরি encapsulated হয়। এবং এখনো, এটি একেবারে কেউ পড়তে এবং এক্স পরিবর্তন করতে পারবেন । কিভাবে যে এমনকি ইন্দ্রিয় তোলে? (ইঙ্গিত: এটা না)

নিচের লাইন: এনক্যাপুলেশন ব্যক্তিগত ফাংশন অ্যাক্সেস করতে পারেন যা ফাংশন নিয়ন্ত্রণ করতে সক্ষম হচ্ছে। এই ফাংশন সংজ্ঞা কোথায় অবস্থিত তা ঠিক নয়।


অপারেটর << এবং অপারেটরের সাথে সম্পর্কিত >> এই অপারেটরদের বন্ধু তৈরি করার কোনও কারণ নেই। এটা সত্য যে তারা সদস্যের কাজ না হওয়া উচিত, তবে তাদের বন্ধু হতে হবে না।

করতে ভাল জিনিস হল পাবলিক মুদ্রণ (ostream &) তৈরি করুন এবং পড়া (আইটি্রিম এবং) ফাংশন। তারপরে, সেই ফাংশনের শর্তে অপারেটর << এবং অপারেটর >> লিখুন। এটি আপনাকে সেই ফাংশনগুলি ভার্চুয়াল করতে সক্ষম করার অতিরিক্ত যোগফল দেয়, যা ভার্চুয়াল সিরিয়ালাইজেশন সরবরাহ করে।


অ্যান্ড্রু এর উদাহরণ আরেকটি সাধারণ সংস্করণ, ভয়ঙ্কর কোড-দম্পতি

parent.addChild(child);
child.setParent(parent);

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

class Parent;

class Object {
private:
    void setParent(Parent&);

    friend void addChild(Parent& parent, Object& child);
};

class Parent : public Object {
private:
     void addChild(Object& child);

     friend void addChild(Parent& parent, Object& child);
};

void addChild(Parent& parent, Object& child) {
    if( &parent == &child ){ 
        wetPants(); 
    }
    parent.addChild(child);
    child.setParent(parent);
}

অন্য কথায় আপনি জনসাধারণের ইন্টারফেসগুলিকে ছোট রাখতে এবং ফ্রেন্ডস ফাংশনে ক্লাস এবং বস্তুগুলির মধ্যে কাটানো ইনভারিয়েন্টগুলি প্রয়োগ করতে পারেন।


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

আসুন বলুন আপনি দুটি বস্তুর তুলনা করতে চান কিনা তা দেখতে সমান। আপনি হয়:

  • তুলনা করার জন্য অ্যাক্সেসার পদ্ধতি ব্যবহার করুন (প্রতিটি ivar চেক এবং সমতা নির্ধারণ)।
  • অথবা, আপনি সরাসরি তাদের জনসাধারণের দ্বারা সব সদস্যদের অ্যাক্সেস করতে পারে।

প্রথম বিকল্পটি নিয়ে সমস্যাটি হল এটি অ্যাক্সেসারগুলির একটি লট হতে পারে যা সরাসরি পরিবর্তনযোগ্য অ্যাক্সেসের চেয়ে সামান্য (ধীর) ধীরে ধীরে পড়তে কঠিন, এবং গুরুতর। দ্বিতীয় পদ্ধতির সাথে সমস্যা হল যে আপনি সম্পূর্ণরূপে encapsulation বিরতি।

কী সুন্দর হবে, যদি আমরা একটি বহিরাগত ফাংশন সংজ্ঞায়িত করতে পারি যা এখনও একটি বর্গের ব্যক্তিগত সদস্যদের অ্যাক্সেস পেতে পারে। আমরা friend কীওয়ার্ড দিয়ে এটি করতে পারি:

class Beer {
public:
    friend bool equal(Beer a, Beer b);
private:
    // ...
};

পদ্ধতিটি equal(Beer, Beer) এখন b এবং b এর ব্যক্তিগত সদস্যদের সরাসরি অ্যাক্সেস রয়েছে (যা char *brand , float percentAlcohol ইত্যাদি হতে পারে।) এটি একটি পরিবর্তিত উদাহরণ, আপনি শীঘ্রই একটি ওভারলোড করা friend কাছে আবেদন করবেন == operator , কিন্তু আমরা যে পেতে হবে।

কিছু জিনিস মনে রাখবেন:

  • একটি friend ক্লাস সদস্য সদস্য হয় না
  • এটি ক্লাসের ব্যক্তিগত সদস্যদের বিশেষ অ্যাক্সেসের সাথে একটি সাধারণ ফাংশন
  • সকল অ্যাক্সেসর এবং মিউটেটরকে বন্ধুদের সাথে প্রতিস্থাপন করবেন না (আপনি সর্বদাই সবকিছু public তুলতে পারেন!)
  • বন্ধুত্ব পারস্পরিক হয় না
  • বন্ধুত্ব সংগ্রাহক হয় না
  • বন্ধুত্ব উত্তরাধিকারসূত্রে প্রাপ্ত হয় না
  • অথবা, সি ++ প্রশ্নাবলী ব্যাখ্যা করে : "আমি আপনাকে আমার বন্ধুত্বের অ্যাক্সেস দেওয়ার কারণে স্বয়ংক্রিয়ভাবে আমার বাচ্চাদের অ্যাক্সেস দেয় না, স্বয়ংক্রিয়ভাবে আপনার বন্ধুদের অ্যাক্সেস দেয় না এবং স্বয়ংক্রিয়ভাবে আমাকে অ্যাক্সেস দেয় না । "

অন্য উপায়টি করার ক্ষেত্রে এটি কঠিন হয়ে গেলে আমি শুধুমাত্র friends ব্যবহার করি। অন্য উদাহরণ হিসাবে, অনেক ভেক্টর গণিত ফাংশনগুলি প্রায়ই Mat2x2 , Mat3x3 , Mat4x4 , Vec2 , Vec3 , Vec4 ইত্যাদির Vec4 কারণে friends হিসাবে তৈরি হয় এবং এটি সর্বত্র অ্যাক্সেসার ব্যবহার করার পরিবর্তে বন্ধুদের পক্ষে এত সহজ। হিসাবে নির্দেশিত, << (সত্যিই ডিবাগিং জন্য সহজ), >> এবং সম্ভবত == অপারেটর প্রয়োগ করা হলে friend প্রায়ই দরকারী, কিন্তু এই মত কিছু জন্য ব্যবহার করা যেতে পারে:

class Birds {
public:
    friend Birds operator +(Birds, Birds);
private:
    int numberInFlock;
};


Birds operator +(Birds b1, Birds b2) {
    Birds temp;
    temp.numberInFlock = b1.numberInFlock + b2.numberInFlock;
    return temp;
}

আমি যেমন বলি, আমি friend প্রায়ই খুব বেশি ব্যবহার করি না, কিন্তু এখনই এবং তারপর এটি আপনার যা দরকার তা। আশাকরি এটা সাহায্য করবে!


আমরা একটি কোম্পানী যেখানে আমি আগে কাজ করেছি একটি আকর্ষণীয় সমস্যা ছিল যেখানে আমরা শালীন প্রভাব বন্ধু ব্যবহার। আমি আমাদের ফ্রেমওয়ার্ক বিভাগে কাজ করেছি আমরা আমাদের কাস্টম ওএসের উপর একটি মৌলিক ইঞ্জিন স্তর ব্যবস্থা তৈরি করেছি। অভ্যন্তরীণভাবে আমরা একটি বর্গ গঠন ছিল:

         Game
        /    \
 TwoPlayer  SinglePlayer

এই সব ক্লাসের কাঠামো অংশ এবং আমাদের দলের দ্বারা রক্ষণাবেক্ষণ ছিল। কোম্পানির তৈরি গেমগুলি গেমসের শিশুদের একটিতে প্রাপ্ত এই ফ্রেমওয়ার্কের উপরে নির্মিত হয়েছিল। ইস্যু ছিল যে গেমটি বিভিন্ন জিনিসের ইন্টারফেস ছিল যা SinglePlayer এবং TwoPlayer অ্যাক্সেসের প্রয়োজন ছিল কিন্তু আমরা ফ্রেমওয়ার্ক ক্লাসগুলির বাইরে প্রকাশ করতে চাইনি। সমাধানটি সেই ইন্টারফেসগুলিকে ব্যক্তিগত করে তুলতে এবং বন্ধুত্বের মাধ্যমে টুপ্লেয়ার এবং একক প্লেয়ার অ্যাক্সেসের অনুমতি দেয়।

সত্যই এই সমগ্র ইস্যুটি আমাদের সিস্টেমের আরও ভাল বাস্তবায়ন দ্বারা সমাধান করা যেতে পারে তবে আমাদের যা ছিল তা আমরা বন্ধ হয়ে গিয়েছিলাম।


আমি শুধুমাত্র বন্ধু-শব্দ ব্যবহার করে unittest সুরক্ষিত ফাংশন। কিছু বলবে যে আপনি সুরক্ষিত কার্যকারিতা পরীক্ষা করা উচিত নয়। আমি, যদিও, নতুন কার্যকারিতা যোগ করার সময় এই খুব দরকারী হাতিয়ার।

যাইহোক, আমি ক্লাস ঘোষণাগুলিতে সরাসরি কীওয়ার্ড ব্যবহার করি না, পরিবর্তে এটির জন্য আমি নিফটি টেমপ্লেট-হ্যাক ব্যবহার করি:

template<typename T>
class FriendIdentity {
public:
  typedef T me;
};

/**
 * A class to get access to protected stuff in unittests. Don't use
 * directly, use friendMe() instead.
 */
template<class ToFriend, typename ParentClass>
class Friender: public ParentClass
{
public:
  Friender() {}
  virtual ~Friender() {}
private:
// MSVC != GCC
#ifdef _MSC_VER
  friend ToFriend;
#else
  friend class FriendIdentity<ToFriend>::me;
#endif
};

/**
 * Gives access to protected variables/functions in unittests.
 * Usage: <code>friendMe(this, someprotectedobject).someProtectedMethod();</code>
 */
template<typename Tester, typename ParentClass>
Friender<Tester, ParentClass> & 
friendMe(Tester * me, ParentClass & instance)
{
    return (Friender<Tester, ParentClass> &)(instance);
}

এটি আমাকে নিম্নলিখিত কাজ করতে সক্ষম করে:

friendMe(this, someClassInstance).someProtectedFunction();

অন্তত জিसीसी এবং এমএসভিসি কাজ করে।


আরেকটি ব্যবহার: বন্ধু (+ ভার্চুয়াল উত্তরাধিকার) একটি বর্গ থেকে প্রাপ্তি এড়াতে ব্যবহার করা যেতে পারে (উর: "একটি বর্গ কমিয়ে আনা") => 1 , 2

2 থেকে:

 class Fred;

 class FredBase {
 private:
   friend class Fred;
   FredBase() { }
 };

 class Fred : private virtual FredBase {
 public:
   ...
 }; 

ক্যানোনিকাল উদাহরণটি ওভারলোড অপারেটর <<। আরেকটি সাধারণ ব্যবহার হেল্পার বা অ্যাডমিন ক্লাসকে আপনার অভ্যন্তরীণগুলিতে অ্যাক্সেস করার অনুমতি দেয়।

এখানে সি ++ বন্ধুদের সম্পর্কে শুনেছি এমন কয়েকটি নির্দেশিকা রয়েছে। শেষ এক বিশেষভাবে স্মরণীয়।

  • আপনার বন্ধুরা আপনার সন্তানের বন্ধু না।
  • আপনার সন্তানের বন্ধু আপনার বন্ধু হয় না।
  • শুধুমাত্র বন্ধু আপনার ব্যক্তিগত অংশ স্পর্শ করতে পারেন।

গাছ উদাহরণটি একটি সুন্দর উদাহরণ: একটি উত্তরাধিকার সম্পর্ক ছাড়া কিছু ভিন্ন শ্রেণীতে প্রয়োগ করা একটি বস্তু থাকার।

সম্ভবত আপনি এটির জন্য একটি কনস্ট্রাক্টর সুরক্ষিত রাখতে এবং আপনার "বন্ধু" কারখানার ব্যবহার করতে বাধ্য করতে পারেন।

ঠিক আছে, ঠিক আছে, আপনি এটা ছাড়া বাঁচতে পারেন।


বন্ধু ফাংশন এবং ক্লাস সাধারণ ক্ষেত্রে ব্রেকিং ইনકેપসুলেশন এড়াতে ক্লাসের ব্যক্তিগত এবং সুরক্ষিত সদস্যদের সরাসরি অ্যাক্সেস প্রদান করে। সর্বাধিক ব্যবহার ostream সঙ্গে: আমরা টাইপ করতে সক্ষম হতে চাই:

Point p;
cout << p;

যাইহোক, এইটিকে পয়েন্টের ব্যক্তিগত তথ্য অ্যাক্সেসের প্রয়োজন হতে পারে, তাই আমরা ওভারলোড হওয়া অপারেটরটি সংজ্ঞায়িত করি

friend ostream& operator<<(ostream& output, const Point& p);

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

আপনি যদি বন্ধুকে ক্লাসের এক্সটেনশান হিসাবে দেখেন তবে তা ইস্যু নয়, যৌক্তিকভাবে কথা বলা। কিন্তু, সেই ক্ষেত্রে, কেন প্রথমে বন্ধুকে ভাড়া করা দরকার?

'বন্ধু' অর্জনের একই জিনিসটি অর্জন করতে, কিন্তু এনক্যাপুলেশন ভেঙ্গে না থাকলে, এটি করতে পারেন:

class A
{
public:
    void need_your_data(B & myBuddy)
    {
        myBuddy.take_this_name(name_);
    }
private:
    string name_;
};

class B
{
public:
    void print_buddy_name(A & myBuddy)
    {
        myBuddy.need_your_data(*this);
    }
    void take_this_name(const string & name)
    {
        cout << name;
    }
}; 

এনক্যাপুলেশনটি ভাঙা হয় না, ক্লাস B এর অভ্যন্তরীণ বাস্তবায়নের অ্যাক্সেসের কোনও অ্যাক্সেস নেই, তবে ফলাফলটি একইরকম যে আমরা B কে বন্ধু হিসাবে ঘোষিত করেছি। কম্পাইলার ফাংশন কলগুলি অপটিমাইজ করবে, তাই এটি একই সরাসরি এক্সেস হিসাবে নির্দেশাবলী।

আমি মনে করি 'বন্ধু' ব্যবহার করে কেবল বিতর্কিত সুবিধার সাথে একটি শর্টকাট, তবে নির্দিষ্ট খরচ।


যখন আপনি একটি কন্টেইনার তৈরি করেন তখন বন্ধু সহজে আসে এবং আপনি সেই ক্লাসের জন্য একটি ইটারারেটর বাস্তবায়ন করতে চান।


সি ++ এর নির্মাতা বলছেন যে কোনও এনক্যাপুলেশন নীতি নকল করছে না এবং আমি তাকে উদ্ধৃত করবো:

"বন্ধু" encapsulation লঙ্ঘন করে? না। এটা না। "ফ্রেন্ড" অ্যাক্সেস দেওয়ার জন্য একটি স্পষ্ট প্রক্রিয়া, যেমন সদস্যতা। আপনি (একটি স্ট্যান্ডার্ড কনফর্মিং প্রোগ্রামে) নিজের উত্সটি সংশোধন না করে নিজেকে শ্রেণীতে অ্যাক্সেস করতে পারবেন।

স্পষ্ট বেশী ...


@roo : এখানে @roo ভাঙ্গা হয় না কারণ ক্লাস নিজেই নিজের ব্যক্তিগত সদস্যদের অ্যাক্সেস করতে পারে তা নির্ধারণ করে। এনক্যাপুলেশনটি শুধুমাত্র ভাঙ্গা হবে যদি এটি ক্লাসের বাইরে হতে পারে, উদাহরণস্বরূপ যদি আপনার operator << ঘোষণা করে যে "আমি ক্লাস foo বন্ধু।"

private ব্যবহার না করে private ব্যবহারের বদলে friend !

আসলে, সি ++ প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী এই উত্তর


friend শব্দ একটি ভাল ব্যবহার সংখ্যা আছে। এখানে দুটি ব্যবহার অবিলম্বে আমার কাছে দৃশ্যমান:

বন্ধু সংজ্ঞা

বন্ধু সংজ্ঞা ক্লাস-স্কোপে একটি ফাংশন সংজ্ঞায়িত করার অনুমতি দেয়, তবে ফাংশনটি সদস্য ফাংশন হিসাবে সংজ্ঞায়িত করা হবে না, তবে এনক্লোসিং নামস্থানটির একটি মুক্ত ফাংশন হিসাবে, এবং আর্গুমেন্ট নির্ভরশীল অনুসন্ধান ব্যতীত সাধারণভাবে দৃশ্যমান হবে না। এটি অপারেটর ওভারলোডিংয়ের জন্য বিশেষ করে দরকারী করে তোলে:

namespace utils {
    class f {
    private:
        typedef int int_type;
        int_type value;

    public:
        // let's assume it doesn't only need .value, but some
        // internal stuff.
        friend f operator+(f const& a, f const& b) {
            // name resolution finds names in class-scope. 
            // int_type is visible here.
            return f(a.value + b.value);
        }

        int getValue() const { return value; }
    };
}

int main() {
    utils::f a, b;
    std::cout << (a + b).getValue(); // valid
}

ব্যক্তিগত সিআরটিপি বেস ক্লাস

কখনও কখনও, আপনি একটি পলিসি প্রাপ্ত হওয়া শ্রেণিতে অ্যাক্সেস প্রয়োজন প্রয়োজন খুঁজে পেতে:

// possible policy used for flexible-class.
template<typename Derived>
struct Policy {
    void doSomething() {
        // casting this to Derived* requires us to see that we are a 
        // base-class of Derived.
        some_type const& t = static_cast<Derived*>(this)->getSomething();
    }
};

// note, derived privately
template<template<typename> class SomePolicy>
struct FlexibleClass : private SomePolicy<FlexibleClass> {
    // we derive privately, so the base-class wouldn't notice that, 
    // (even though it's the base itself!), so we need a friend declaration
    // to make the base a friend of us.
    friend class SomePolicy<FlexibleClass>;

    void doStuff() {
         // calls doSomething of the policy
         this->doSomething();
    }

    // will return useful information
    some_type getSomething();
};

আপনি this উত্তর যে জন্য একটি অনির্ধারিত উদাহরণ পাবেন। this উত্তর ব্যবহার করে অন্য কোড। ডাটা-সদস্য-পয়েন্টারগুলি ব্যবহার করে প্রাপ্ত শ্রেণির ডাটা-ক্ষেত্রগুলি অ্যাক্সেস করতে সক্ষম হওয়ার জন্য সিআরটিপি বেসটি এই পয়েন্টারটিকে ধারণ করে।


এটি একটি প্রকৃত ব্যবহার ক্ষেত্রে পরিস্থিতি নাও হতে পারে তবে ক্লাসগুলির মধ্যে বন্ধুর ব্যবহারকে চিত্রিত করতে সহায়তা করতে পারে।

ক্লাব হাউস

class ClubHouse {
public:
    friend class VIPMember; // VIP Members Have Full Access To Class
private:
    unsigned nonMembers_;
    unsigned paidMembers_;
    unsigned vipMembers;

    std::vector<Member> members_;
public:
    ClubHouse() : nonMembers_(0), paidMembers_(0), vipMembers(0) {}

    addMember( const Member& member ) { // ...code }   
    void updateMembership( unsigned memberID, Member::MembershipType type ) { // ...code }
    Amenity getAmenity( unsigned memberID ) { // ...code }

protected:
    void joinVIPEvent( unsigned memberID ) { // ...code }

}; // ClubHouse

সদস্য ক্লাস এর

class Member {
public:
    enum MemberShipType {
        NON_MEMBER_PAID_EVENT,   // Single Event Paid (At Door)
        PAID_MEMBERSHIP,         // Monthly - Yearly Subscription
        VIP_MEMBERSHIP,          // Highest Possible Membership
    }; // MemberShipType

protected:
    MemberShipType type_;
    unsigned id_;
    Amenity amenity_;
public:
    Member( unsigned id, MemberShipType type ) : id_(id), type_(type) {}
    virtual ~Member(){}
    unsigned getId() const { return id_; }
    MemberShipType getType() const { return type_; }
    virtual void getAmenityFromClubHouse() = 0       
};

class NonMember : public Member {
public:
   explicit NonMember( unsigned id ) : Member( id, MemberShipType::NON_MEMBER_PAID_EVENT ) {}   

   void getAmenityFromClubHouse() override {
       Amenity = ClubHouse::getAmenity( this->id_ );
    }
};

class PaidMember : public Member {
public:
    explicit PaidMember( unsigned id ) : Member( id, MemberShipType::PAID_MEMBERSHIP ) {}

    void getAmenityFromClubHouse() override {
       Amenity = ClubHouse::getAmenity( this->id_ );
    }
};

class VIPMember : public Member {
public:
    friend class ClubHouse;
public:
    explicit VIPMember( unsigned id ) : Member( id, MemberShipType::VIP_MEMBERSHIP ) {}

    void getAmenityFromClubHouse() override {
       Amenity = ClubHouse::getAmenity( this->id_ );
    }

    void attendVIPEvent() {
        ClubHouse::joinVIPEvent( this->id );
    }
};

সুযোগ-সুবিধা

class Amenity{};

আপনি এখানে এই ক্লাসের সম্পর্ক তাকান; ClubHouse বিভিন্ন ধরনের সদস্যপদ এবং সদস্যপদ অ্যাক্সেস বিভিন্ন ঝুলিতে। সদস্যরা সবগুলি একটি সুপার বা বেস ক্লাস থেকে উদ্ভূত হয় কারণ তারা সকলেই একটি আইডি ভাগ করে এবং একটি বুদ্ধিমান টাইপ যা সাধারণ এবং বাইরের ক্লাস বেস ক্লাসে পাওয়া অ্যাক্সেস ফাংশনগুলির মাধ্যমে তাদের আইডি এবং প্রকারগুলি অ্যাক্সেস করতে পারে।

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

সুতরাং ভিআইপিএমবার এবং ক্লাবহাউজের সাথে এটি অ্যাক্সেসের দুটি রাস্তার রাস্তা যেখানে অন্যান্য সদস্য শ্রেণীগুলি সীমিত।


বিভিন্ন শ্রেণীর (অন্যের কাছ থেকে উত্তরাধিকারসূত্রে প্রাপ্ত নয়) অন্য শ্রেণীতে ব্যক্তিগত বা সুরক্ষিত সদস্যদের ব্যবহার করার সময় আপনি বন্ধুত্ব ব্যবহার করতে পারেন।

বন্ধু ফাংশনগুলির সাধারণ ব্যবহারের ক্ষেত্রে উভয় প্রাইভেট বা সুরক্ষিত সদস্যদের অ্যাক্সেস করা দুটি পৃথক ক্লাসের মধ্যে পরিচালিত হয় অপারেশন।

http://www.cplusplus.com/doc/tutorial/inheritance/ থেকে ।

আপনি এই উদাহরণটি দেখতে পারেন যেখানে সদস্যহীন পদ্ধতিটি ক্লাসের ব্যক্তিগত সদস্যদের অ্যাক্সেস করে। ক্লাসের বন্ধু হিসেবে এই ক্লাসে এই পদ্ধতিটি ঘোষণা করতে হবে।

// friend functions
#include <iostream>
using namespace std;

class Rectangle {
    int width, height;
  public:
    Rectangle() {}
    Rectangle (int x, int y) : width(x), height(y) {}
    int area() {return width * height;}
    friend Rectangle duplicate (const Rectangle&);
};

Rectangle duplicate (const Rectangle& param)
{
  Rectangle res;
  res.width = param.width*2;
  res.height = param.height*2;
  return res;
}

int main () {
  Rectangle foo;
  Rectangle bar (2,3);
  foo = duplicate (bar);
  cout << foo.area() << '\n';
  return 0;
}

বন্ধু ঘোষণা জন্য রেফারেন্স হিসাবে বলেছেন:

বন্ধুর ঘোষণাপত্র একটি শ্রেণির শরীরের মধ্যে উপস্থিত হয় এবং বন্ধুত্বের ঘোষণাটি প্রদর্শিত হয় এমন ক্লাসের ব্যক্তিগত ও সুরক্ষিত সদস্যদের একটি ফাংশন বা অন্য ক্লাস অ্যাক্সেস দেয় ।

তাই শুধু একটি অনুস্মারক হিসাবে, উত্তর কিছু প্রযুক্তিগত ত্রুটি আছে যা বলে যে friendশুধুমাত্র সুরক্ষিত সদস্যদের পরিদর্শন করতে পারেন ।


বন্ধু কলব্যাক জন্য দরকারী। আপনি স্ট্যাটিক পদ্ধতি হিসাবে callbacks বাস্তবায়ন করতে পারে

class MyFoo
{
private:
    static void callback(void * data, void * clientData);
    void localCallback();
    ...
};

যেখানে অভ্যন্তরীণ callbackকল localCallback, এবং clientDataএটি আপনার দৃষ্টান্ত আছে। আমার মতে,

বা ...

class MyFoo
{
    friend void callback(void * data, void * callData);
    void localCallback();
}

এইটি কীভাবে সি-পি-স্টাইল ফাংশন হিসাবে সিপিএ-তে সংজ্ঞায়িত করা যায় এবং ক্লাসটিকে বিভক্ত করে না।

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

হেডারের মধ্যে:

class MyFooPrivate;
class MyFoo
{
    friend class MyFooPrivate;
public:
    MyFoo();
    // Public stuff
private:
    MyFooPrivate _private;
    // Other private members as needed
};

সিপিপি,

class MyFooPrivate
{
public:
   MyFoo *owner;
   // Your complexity here
};

MyFoo::MyFoo()
{
    this->_private->owner = this;
}

ডাউনস্ট্রীম এই ভাবে দেখতে হবে না যে জিনিস লুকাতে সহজ হয়ে যায়।


সম্ভবত আমি উপরে উত্তর থেকে কিছু মিস করেছি কিন্তু encapsulation অন্য একটি গুরুত্বপূর্ণ ধারণা বাস্তবায়ন লুকানো হয়। ব্যক্তিগত ডেটা সদস্যদের অ্যাক্সেস হ্রাস করা (একটি শ্রেণির বাস্তবায়ন বিশদ) কোডটির পরে আরও সহজ সংশোধন করে। যদি কোনও বন্ধু সরাসরি ব্যক্তিগত ডেটা অ্যাক্সেস করে তবে বাস্তবায়ন ডেটা ক্ষেত্রগুলির (ব্যক্তিগত তথ্য) কোনও পরিবর্তন, সেই ডেটা অ্যাক্সেস করে কোডটি ভাঙ্গতে পারে। অ্যাক্সেস পদ্ধতি ব্যবহার করে বেশিরভাগই এই নির্মূল করে। আমি মনে করি মোটামুটি গুরুত্বপূর্ণ।





friend