সি ++ এ কখন আপনার 'বন্ধু' ব্যবহার করা উচিত?


354

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

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


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


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

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

সামান্য ব্যবহারিক অভিজ্ঞতার সাথে ওওপি "পিউরিস্টস" যুক্তি দেয় যে বন্ধুটি ওওপি নীতিগুলি লঙ্ঘন করে, কারণ কোনও শ্রেণীর উচিত তার ব্যক্তিগত রাষ্ট্রের একমাত্র রক্ষণাবেক্ষণকারী। এটি ঠিক আছে, যতক্ষণ না আপনি এমন একটি সাধারণ পরিস্থিতির মুখোমুখি হন যেখানে দুটি শ্রেণির ভাগ করে নেওয়া ব্যক্তিগত রাষ্ট্র বজায় রাখা দরকার।
কালাস

উত্তর:


335

প্রথমত (আইএমও) এমন লোকদের কথা শুনবেন না যারা বলে friendযে দরকারী নয়। এটা কার্যকরী. অনেক পরিস্থিতিতে আপনার কাছে ডেটা বা কার্যকারিতা সহ এমন সামগ্রী থাকবে যা সর্বজনীনভাবে উপলভ্য হওয়ার উদ্দেশ্যে নয়। এটি বিশেষত অনেক লেখকের সাথে বড় কোডবেসের ক্ষেত্রে সত্য, যারা কেবলমাত্র বিভিন্ন অঞ্চলের সাথে অতিপরিচয়ভাবে পরিচিত হতে পারেন।

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

উত্তরে;

friendসুনির্দিষ্টভাবে উল্লেখ করা বর্গ বন্ধু বিবৃতি উপার্জন মধ্যে সংরক্ষিত ডেটা বা কার্যকারিতা মনোনীত বর্গ অ্যাক্সেস করতে দেয়। উদাহরণস্বরূপ নীচের কোডটিতে যে কোনও শিশু তার নামের জন্য জিজ্ঞাসা করতে পারে তবে কেবল মা এবং সন্তানের নাম পরিবর্তন হতে পারে।

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

class Child
{
//Mother class members can access the private parts of class Child.
friend class Mother;

public:

  string name( void );

protected:

  void setName( string newName );
};

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

5
আপনি কি দয়া করে (সিপিপি-স্তরের কংক্রিটের ক্লাস) এবং (মুখোশযুক্ত টাইপিডেফ), অ্যান্ড্রু সম্পর্কে আরও বলতে পারেন ?
ওমরথম্যান

18
এই উত্তরটি অনুপ্রেরণামূলক উদাহরণ friendপ্রদানের পরিবর্তে কী তা বোঝাতে বেশি মনোযোগী বলে মনে হচ্ছে । উইন্ডো / উইন্ডো ম্যানেজার উদাহরণটি প্রদর্শিত উদাহরণের চেয়ে ভাল তবে খুব অস্পষ্ট। এই উত্তরটি প্রশ্নের এনক্যাপসুলেশন অংশকেও সম্বোধন করে না।
bames53

4
সুতরাং কার্যকরভাবে 'বন্ধু' বিদ্যমান কারণ সি ++ এর এমন কোনও প্যাকেজ সম্পর্কে ধারণা নেই যাতে সমস্ত সদস্য বাস্তবায়নের বিশদটি ভাগ করতে পারে? আমি সত্যিকারের বিশ্বের উদাহরণে সত্যই আগ্রহী হব।
weberc2

1
@ ওমগতেচি আপনার যদি এটি করতে হবে না যদি সি ++ এর প্যাকেজগুলির ধারণা থাকে, তবে এটি আমার আগের বক্তব্যের সাথে সামঞ্জস্য রয়েছে। এখানে গো এর একটি উদাহরণ রয়েছে যা ব্যক্তিগত সদস্যদের অ্যাক্সেস করতে বন্ধুদের পরিবর্তে প্যাকেজগুলি ব্যবহার করে: play.golang.org/p/xnade4GBAL
weberc2

162

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

বলার অপেক্ষা রাখে না যে আমি বন্ধু কীওয়ার্ডটি আপনার ডিজাইনের একটি প্রয়োজনীয় উপাদান হিসাবে ব্যবহার করব না।


ঠিক এটিই আমি এটির জন্য ব্যবহার করি। এটি বা কেবল সদস্য ভেরিয়েবলগুলি সুরক্ষিত হিসাবে সেট করুন। এটি কেবলমাত্র লজ্জার বিষয় এটি সি ++ / সিএলআইয়ের জন্য কাজ করে না :-(
জন কেজ

12
ব্যক্তিগতভাবে আমি এটিকে নিরুৎসাহিত করব। সাধারণত আপনি একটি ইন্টারফেস পরীক্ষা করছেন, অর্থাত্ সেটগুলি আউটপুট (গুলি) এর প্রত্যাশিত সেট দেয়। আপনার অভ্যন্তরীণ ডেটা পরীক্ষা করার প্রয়োজন কেন?
গ্রিম

55
@ গ্র্যাম: কারণ একটি ভাল পরীক্ষার পরিকল্পনায় হোয়াইট বক্স এবং ব্ল্যাক বক্স পরীক্ষা উভয়ই অন্তর্ভুক্ত।
বেন ভয়েগট

1
আমি উত্তর সম্পর্কে পুরোপুরি ব্যাখ্যা হিসাবে, গ্র্যামিমের সাথে একমত হতে চাইছি ।
অ্যালেক্সিস লেকার্ক

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

93

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();
};

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


হাই, আমি যখন আপনার সিআরটিপি চেষ্টা করি তখন আমি একটি সিনট্যাক্স ত্রুটি পাই (এক্সকোড 4 এ)। এক্সকোড বিশ্বাস করে যে আমি একটি শ্রেণির টেম্পলেট উত্তরাধিকারী হওয়ার চেষ্টা করছি। গোমরাহী ঘটে P<C>মধ্যে template<template<typename> class P> class C : P<C> {};জানায় "শ্রেণী টেমপ্লেট সি ব্যবহারের টেমপ্লেট আর্গুমেন্ট প্রয়োজন"। আপনি কি একই সমস্যার সমাধান করেছেন বা সম্ভবত কোনও সমাধান জানেন?
বেনিডিচ

@ বেনিডিচ প্রথম নজরে, এটি অপর্যাপ্ত সি ++ বৈশিষ্ট্য সমর্থন দিয়ে আপনি যে ধরণের ত্রুটি পাবেন তা দেখে মনে হচ্ছে। যা সংকলকগুলির মধ্যে বেশ সাধারণ। এর FlexibleClassমধ্যে ব্যবহার FlexibleClassসুস্পষ্টভাবে তার নিজস্ব ধরণের বোঝায়।
ইয়াক্ক - অ্যাডাম নেভ্রামুমন্ট

@ বেনেডিচ: শ্রেণি বডি থেকে শ্রেণি টেম্পলেটটির নাম ব্যবহারের নিয়মগুলি সি ++ 11 দিয়ে পরিবর্তিত হয়েছে। আপনার সংকলকটিতে সি ++ 11 মোড সক্ষম করার চেষ্টা করুন।
বেন ভয়েগট

ভিজ্যুয়াল স্টুডিও 2015 এ এই পাবলিক যুক্ত করুন: চ () {}; f (int_type t): মান (টি) {}; এই সংকলক ত্রুটি প্রতিরোধ করতে: ত্রুটি C2440: '<function-style-cast>': 'utils :: f :: int_type' থেকে 'utils :: f' নোট রূপান্তর করতে পারে না: কোনও নির্মাণকারীর উত্সের ধরণ, বা কনস্ট্রাক্টর নিতে পারেনি ওভারলোড রেজোলিউশন অস্পষ্ট ছিল
দামিয়ান

41

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

friendব্যবহার প্রতিস্থাপন, ব্যবহার publicনা private!

আসলে, সি ++ এফএকিউ এর উত্তর ইতিমধ্যে দিয়েছে


14
"বন্ধু জনসাধারণের ব্যবহার প্রতিস্থাপন করে, ব্যক্তিগত ব্যবহারের পরিবর্তে না!", আমি দ্বিতীয় যে
ওয়ালিদ আইসা

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

12
সেই এফকিউএর বেশিরভাগটি সম্পূর্ণ ব্ল্যাক্স :)
রামা-জেকা তোতি

1
@ কনরাড: "এখানে একমাত্র আসল পর্যবেক্ষণটি হ'ল সি ++ কেবল সংকলন-সময়েই এনক্যাপসুলেশন নিশ্চিত করে।" কোনও ভাষা রানটাইম এ এটি নিশ্চিত করে? যতদূর আমি জানি, ব্যক্তিগত সদস্যদের (এবং ফাংশনগুলি, যে ভাষাগুলির জন্য পয়েন্টারগুলি প্রথম শ্রেণীর অবজেক্ট হিসাবে ফাংশন বা ফাংশনগুলিতে অনুমতি দেয়) জন্য রেফারেন্সগুলি সি #, জাভা, পাইথন এবং আরও অনেকগুলিতে অনুমোদিত।
আন্দ্রে কারন

@ আন্দ্রে: জেভিএম এবং সিএলআর আসলে যতদূর জানি এটি এটিকে নিশ্চিত করতে পারে। আমি জানি না এটি সর্বদা সম্পন্ন হয়েছে কিনা তবে আপনি এই জাতীয় অনুপ্রবেশের বিরুদ্ধে প্যাকেজ / সমাবেশগুলি সুরক্ষিত করতে পারেন (যদিও এটি নিজে কখনও করেন নি)।
কনরাড রুডলফ

27

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

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

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

" ক্যানোনিকাল উদাহরণ হ'ল ওভারলোড অপারেটর <<। " friendআমি অনুমান করি না ব্যবহারের ক্যানোনিকাল ।
কৌতূহলী

16

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

এটি কীভাবে এনক্যাপসুলেশন ভাঙ্গবে?

আপনি কোনও ডেটা সদস্যের সীমাবদ্ধ অ্যাক্সেসের অনুমতি দিলে আপনি এনক্যাপসুলেশন ভেঙে দেন । নিম্নলিখিত ক্লাস বিবেচনা করুন:

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", তারা মানে না "ব্যক্তিগত সদস্যদের নির্বিচারে ব্যবহারের থেকে রক্ষা করা হবে", কিন্তু "একটি Java শ্রেণি যেখানে শুধুমাত্র এক্সেস ব্যক্তিগত সদস্যদের সক্ষম ফাংশন, বর্গ সদস্য", যদিও এটি সম্পূর্ণ অর্থহীন বিষয় জন্য বিভিন্ন কারণে

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

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

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

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

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


10

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

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);
}

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


6
এর জন্য কারও বন্ধুর দরকার পড়বে কেন? কেন addChildসদস্য ফাংশনটি পিতামাতাকে সেট করতে দেয় না ?
নওয়াজ

1
আরও ভাল উদাহরণ setParentএকটি বন্ধু তৈরি করা হবে , যেহেতু আপনি ক্লায়েন্টদের পিতামাতার পরিবর্তনের অনুমতি দিতে চান না যেহেতু আপনি এটিকে বিভাগের addChild/ removeChildবিভাগে পরিচালনা করছেন ।
ইলিশার

8

আপনি ব্যক্তিগত / সুরক্ষিত / পাবলিক রাইট ব্যবহার করে সদস্য এবং কার্যকারিতার অ্যাক্সেসের অধিকারগুলি নিয়ন্ত্রণ করেন? সুতরাং এই 3 টি স্তরের প্রতিটির ধারণাটি পরিষ্কার, তবে এটি স্পষ্ট হওয়া উচিত যে আমরা কিছু মিস করছি ...

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

সুতরাং বন্ধু আপনাকে রক সলিড অবজেক্ট বিচ্ছিন্নকরণের নমনীয়তা পেতে দেয় তবে আপনি যে জিনিসগুলি ন্যায়সঙ্গত বলে মনে করেন সেগুলির জন্য একটি "লুফোল" তৈরি করার অনুমতি দেয়।

আমার ধারণা লোকেরা বলে এটির প্রয়োজন নেই কারণ সবসময় এমন একটি নকশা থাকে যা এটি না করেই করতে পারে। আমি মনে করি এটি বৈশ্বিক চলকগুলির আলোচনার সাথে সমান: আপনার এগুলি কখনও ব্যবহার করা উচিত নয়, এগুলি ছাড়া সর্বদা একটি উপায় আছে ... তবে বাস্তবে আপনি এমন ঘটনা দেখতে পান যেখানে এটি (প্রায়) সবচেয়ে মার্জিত উপায় হয়ে যায়। .. আমার মনে হয় বন্ধুদের ক্ষেত্রেও এটি একই ঘটনা।

এটি কোনও সেটিং ফাংশনটি ব্যবহার না করেই আপনাকে সদস্য ভেরিয়েবল অ্যাক্সেস করতে দেওয়া ছাড়া সত্যই কোনও ভাল কাজ করে না

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


2
কেমন আছে friendএকটি ঘুলঘুলি? এটি শ্রেণীর তালিকাভুক্ত পদ্ধতিগুলি তার ব্যক্তিগত সদস্যদের অ্যাক্সেস করতে দেয়। এটি এখনও স্বেচ্ছাসেবীর কোড তাদের অ্যাক্সেস করতে দেয় না। যেমন এটি কোনও পাবলিক সদস্য কার্য থেকে আলাদা নয়।
জাল্ফ

আপনি সি ++ তে জাভা প্যাকেজ-স্তরের অ্যাক্সেস পেতে যতটা কাছাকাছি বন্ধু। @ জালফ - বন্ধু ক্লাসগুলি (যেমন কারখানার ক্লাস) সম্পর্কে কী?
ওগ্রে গীতসংহিতা

1
@ অগ্রে: তাদের কী হবে? আপনি এখনও নির্দিষ্টভাবে সেই শ্রেণিটি দিচ্ছেন এবং ক্লাসের ইন্টার্নালগুলিতে অন্য কারও অ্যাক্সেস নেই। আপনি নিজের শ্রেণীর সাথে স্ক্রু করতে স্বেচ্ছাসেবী অজানা কোডের জন্য গেটটি উন্মুক্ত রেখে দিচ্ছেন না।
জলফ

8

বন্ধুত্বের অ্যাক্সেস ব্যবহারের জন্য আমি সহজ জায়গা খুঁজে পেয়েছি: ব্যক্তিগত ফাংশনের ইউনিটেস্ট।


তবে এর জন্য কি কোনও পাবলিক ফাংশন ব্যবহার করা যেতে পারে? বন্ধু অ্যাক্সেস ব্যবহার করে কী সুবিধা?
ঝেং কুয়ে

@ মাভারোবোট আপনি কি নিজের প্রশ্নের বিস্তারিত বর্ণনা করতে পারবেন?
ভ্লাদিমিরস

5

আপনি যখন কোনও ধারক তৈরি করছেন তখন বন্ধুটি কাজে আসে এবং আপনি সেই শ্রেণীর জন্য একটি পুনরুক্তি প্রয়োগ করতে চান।


4

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

         Game
        /    \
 TwoPlayer  SinglePlayer

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

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


4

সংক্ষিপ্ত উত্তরটি হবে: বন্ধুর ব্যবহার করুন যখন এটি বাস্তবে এনক্যাপসুলেশন উন্নত করে । পঠনযোগ্যতা এবং ব্যবহারযোগ্যতা উন্নত করা (অপারেটর << এবং >> ক্যানোনিকাল উদাহরণ) এটিও একটি ভাল কারণ।

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


" অপারেটর << এবং >> হ'ল আধ্যাত্মিক উদাহরণ " নং বরং ক্যানোনিকাল কাউন্টার উদাহরণ
কৌতূহলী

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

" কারণ তাদের সদস্য করা তাদের ব্যবহারকে বিশ্রী করে তুলবে " "স্পষ্টতই, সদস্যবিহীন বা সদস্যদের পরিবর্তে মান শ্রেণির সদস্য তৈরি operator<<এবং operator>>সদস্যরা i|ostreamপছন্দসই বাক্য গঠন সরবরাহ করবে না এবং আমি এটি প্রস্তাব দিচ্ছি না । " আমি সেই মামলার কথা বলছি যখন সেই অপারেটরদের ব্যক্তিগত ডেটা অ্যাক্সেস করতে হবে " আমি কেন পুরোপুরি দেখতে পাই না কেন ইনপুট / আউটপুট অপারেটরদের ব্যক্তিগত সদস্যদের অ্যাক্সেসের প্রয়োজন হবে।
কৌতূহলী

4

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

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

পরিষ্কারের চেয়েও বেশি ...


@ কুরিয়াসগুয়ে: টেমপ্লেটগুলির ক্ষেত্রেও এটি সত্য।
নওয়াজ

@ নাওয়াজ টেমপ্লেট বন্ধুত্ব মঞ্জুর হতে পারে তবে যে কেউ বন্ধুত্বের অনুদানের শ্রেণি পরিবর্তন না করেই একটি নতুন আংশিক বা স্পষ্ট বিশেষায়িতকরণ করতে পারে। আপনি যখন এটি করেন তখন ওডিআর লঙ্ঘনের বিষয়ে সাবধান হন। এবং যাইহোক এটি না।
কৌতূহলী

3

অন্য ব্যবহার: বন্ধু (+ ভার্চুয়াল উত্তরাধিকার) কোনও শ্রেণি থেকে প্রাপ্ত এড়ানোর জন্য ব্যবহার করা যেতে পারে (ওরফে: "একটি শ্রেণীকে অবিভাজ্য করুন") => 1 , 2

2 থেকে :

 class Fred;

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

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

3

টিডিডি করতে অনেকবার আমি সি ++ তে 'বন্ধু' কীওয়ার্ড ব্যবহার করেছি।

বন্ধু কি আমার সম্পর্কে সব জানতে পারে?


আপডেট হয়েছে: বাজার্ন স্ট্রস্ট্রপ সাইট থেকে "বন্ধু" কীওয়ার্ড সম্পর্কে এই মূল্যবান উত্তরটি পেয়েছি ।

"বন্ধু" সদস্যতার মতোই অ্যাক্সেস মঞ্জুর করার জন্য একটি সুস্পষ্ট প্রক্রিয়া।


3

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

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

  • তুলনা করতে অ্যাক্সেসর পদ্ধতি ব্যবহার করুন (প্রতিটি আইভার পরীক্ষা করে সমতা নির্ধারণ করুন)।
  • অথবা, আপনি সমস্ত সদস্যকে সরাসরি জনসাধারণের দ্বারা অ্যাক্সেস করতে পারবেন।

প্রথম বিকল্পটির সমস্যাটি হ'ল এটি প্রচুর পরিমাণে অ্যাক্সেসর হতে পারে যা সরাসরি পরিবর্তনশীল অ্যাক্সেসের চেয়ে ধীরে ধীরে (সামান্য) কম পড়া, পড়ার পক্ষে শক্ত এবং জটিল। দ্বিতীয় পদ্ধতির সমস্যাটি হ'ল আপনি সম্পূর্ণভাবে এনক্যাপসুলেশনটি ভেঙে ফেলেন।

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

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

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

কয়েকটি বিষয় লক্ষণীয়:

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

friendsএটি কেবল তখনই ব্যবহৃত হয় যখন এটি অন্যভাবে করা খুব কঠিন। অন্য একটি উদাহরণ হিসাবে অনেক ভেক্টর গণিতশাস্ত্র ফাংশন প্রায়শই নির্মিত friendsপুরোনো কারণে Mat2x2, Mat3x3, Mat4x4, Vec2, Vec3, Vec4, ইত্যাদি এবং এটা বন্ধু হতে বদলে সর্বত্র accessors ব্যবহার করতে হবে ঠিক তাই অনেক সহজ। যেমনটি উল্লেখ করা হয়েছে, 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খুব বেশি ঘন ঘন ব্যবহার করি না , তবে এখনই এবং পরে আপনার প্রয়োজন কেবল এটি। আশাকরি এটা সাহায্য করবে!


2

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

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


" অপারেটরের সাথে << এবং অপারেটর >> এই অপারেটরগুলিকে বন্ধু বানানোর কোনও ভাল কারণ নেই " "একেবারে সঠিক। " এটি আপনাকে সেই ফাংশনগুলিকে ভার্চুয়াল তৈরি করার অনুমতি দেওয়ার অতিরিক্ত সুবিধা দেয়, " যদি প্রশ্নে শ্রেণিটি উদ্দীপনার উদ্দেশ্যে করা হয় তবে হ্যাঁ। নইলে কেন বিরক্ত হয়?
কৌতূহলী

আমি উত্তর পাই না কেন এই উত্তরটি দু'বার হ্রাস পেয়েছিল - এবং এমনকি কোনও ব্যাখ্যা ছাড়াই! এটা নিষ্ঠুর.
কৌতূহলী

ভার্চুয়াল একটি পারফেক্ট হিট যোগ করবে যা সিরিয়ালাইজেশনে বেশ বড় হতে পারে
পলম

2

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

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

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();

কমপক্ষে জিসিসি এবং এমএসভিসি তে কাজ করে।


2

সি ++ এ "বন্ধু" কীওয়ার্ড অপারেটর ওভারলোডিং এবং ব্রিজ তৈরিতে কার্যকর is

১) অপারেটর ওভারলোডিংয়ে বন্ধু কীওয়ার্ড: অপারেটর ওভারলোডিংয়ের
উদাহরণ: ধরা যাক যে আমাদের একটি ক্লাস "পয়েন্ট" রয়েছে যার দুটি ফ্লোট ভেরিয়েবল
"x" (এক্স-কো-অর্ডিনেটের জন্য) এবং "y" (y- স্থানাঙ্কের জন্য) রয়েছে। এখন আমাদের ওভারলোড "<<"(এক্সট্রাকশন অপারেটর) যেমন আমাদের কল "cout << pointobj"করতে হবে তবে এটি x এবং y স্থানাঙ্ক (যেখানে পয়েন্টটোবিজে ক্লাস পয়েন্টের একটি বস্তু) মুদ্রণ করবে। এটি করার জন্য আমাদের দুটি বিকল্প রয়েছে:

   1. ওভারলোড "অপারেটর << ()" "ostream" শ্রেণিতে ফাংশন।
   "ওভারলোড" অপারেটর << () "" পয়েন্ট "শ্রেণিতে ফাংশন।
এখন প্রথম বিকল্পটি ভাল নয় কারণ আমাদের যদি কিছু ভিন্ন শ্রেণীর জন্য আবার এই অপারেটরটির ওভারলোডের প্রয়োজন হয় তবে আমাদের আবার "ostream" শ্রেণিতে পরিবর্তন আনতে হবে।
সে কারণেই দ্বিতীয়টি সেরা বিকল্প। এখন সংকলক "operator <<()"ফাংশন কল করতে পারেন :

   1.অস্ট্রিমে অবজেক্ট cout.As: cout.operator << (পয়েন্টটোজ) (ফর্ম ষ্ট্রিম শ্রেণি) ব্যবহার করা হচ্ছে। 
2. কোনও অবজেক্ট ছাড়াই কল করুন s যেমন: অপারেটর << (কাউট, পয়েন্টটোজ) (পয়েন্ট ক্লাস থেকে)।

বীকজ আমরা পয়েন্ট শ্রেণিতে ওভারলোডিং বাস্তবায়ন করেছি। সুতরাং কোনও বস্তু ছাড়াই এই ফাংশনটি "friend"কল করতে আমাদের কীওয়ার্ড যুক্ত করতে হবে কারণ আমরা কোনও বস্তু ছাড়াই একটি বন্ধু ফাংশন বলতে পারি। এখন ফাংশন ঘোষণাটি হ'ল:
"friend ostream &operator<<(ostream &cout, Point &pointobj);"

২) ব্রিজ তৈরির ক্ষেত্রে বন্ধু কীওয়ার্ড:
ধরুন আমাদের এমন একটি ফাংশন তৈরি করতে হবে যাতে আমাদের দুটি বা ততোধিক শ্রেণীর ব্যক্তিগত সদস্যকে (সাধারণত "সেতু" বলা হয়) অ্যাক্সেস করতে হবে। এটি কীভাবে করবেন:
কোনও শ্রেণীর ব্যক্তিগত সদস্য অ্যাক্সেস করার জন্য এটি class শ্রেণীর সদস্য হওয়া উচিত। এখন অন্যান্য শ্রেণীর প্রাইভেট সদস্য অ্যাক্সেস করার জন্য প্রতিটি শ্রেণীর সেই ফাংশনটিকে ফ্রেন্ড ফাংশন হিসাবে ঘোষণা করা উচিত। উদাহরণস্বরূপ: ধরুন এখানে দুটি এবং এ এবং বি শ্রেণি রয়েছে একটি ক্রিয়াকলাপ "funcBridge()"উভয় শ্রেণির ব্যক্তিগত সদস্যকে অ্যাক্সেস করতে চায়। তারপরে উভয় শ্রেণীরই ঘোষণা "funcBridge()"করা উচিত :
friend return_type funcBridge(A &a_obj, B & b_obj);

আমি মনে করি এটি বন্ধু কীওয়ার্ড বুঝতে সাহায্য করবে।


2

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

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

সুতরাং কেবল একটি অনুস্মারক হিসাবে, উত্তরের কয়েকটিতে প্রযুক্তিগত ত্রুটি রয়েছে যা বলে যে friendকেবল সুরক্ষিত সদস্যদের দেখতে যেতে পারে।


1

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

সম্ভবত আপনার প্রয়োজন হতে পারে কোনও নির্মাণকারী সুরক্ষিত রাখতে এবং লোককে আপনার "বন্ধু" কারখানাটি ব্যবহার করতে বাধ্য করুন force

... ঠিক আছে, সত্যি বলতে গেলে আপনি এগুলি ছাড়া বাঁচতে পারবেন।


1

টিডিডি করতে অনেকবার আমি সি ++ তে 'বন্ধু' কীওয়ার্ড ব্যবহার করেছি।
বন্ধু কি আমার সম্পর্কে সব জানতে পারে?

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


1

একটি নির্দিষ্ট উদাহরণ যেখানে আমি ব্যবহার করি friendতা হল সিঙ্গলটন ক্লাস তৈরি করার সময় । friendশব্দ আমাকে একটি অ্যাকসেসর ফাংশন, যা সবসময় বর্গ একটি "GetInstance ()" পদ্ধতি থাকার চেয়ে বেশি সংক্ষিপ্ত তৈরি করতে দেয়।

/////////////////////////
// Header file
class MySingleton
{
private:
    // Private c-tor for Singleton pattern
    MySingleton() {}

    friend MySingleton& GetMySingleton();
}

// Accessor function - less verbose than having a "GetInstance()"
//   static function on the class
MySingleton& GetMySingleton();


/////////////////////////
// Implementation file
MySingleton& GetMySingleton()
{
    static MySingleton theInstance;
    return theInstance;
}

এটি স্বাদের বিষয় হতে পারে তবে আমি মনে করি না যে কয়েকটি কী-স্ট্রোক সংরক্ষণ করা এখানে বন্ধুর ব্যবহারকে ন্যায্য বলে প্রমাণিত করে। গেটমাইসিংলেটন () ক্লাসের একটি স্ট্যাটিক পদ্ধতি হওয়া উচিত।
গর্পিক

প্রাইভেট সি-টর মাইসিংটনকে ইনস্ট্যান্ট করতে কোনও বন্ধু-বান্ধব ফাংশনটিকে অস্বীকার করবে, তাই এখানে বন্ধু কীওয়ার্ডটি প্রয়োজন।
জেবিআরউইলকিনসন

@ গর্পিক " এটি স্বাদের বিষয় হতে পারে তবে আমি মনে করি না যে কয়েকটি কীস্ট্রোক সংরক্ষণ করা এখানে বন্ধুর ব্যবহারকে ন্যায্যতাযুক্ত করে। " এটি করে does যাইহোক, একটি নির্দিষ্ট "ন্যায়সঙ্গততা" প্রয়োজন friendহয় না , যখন সদস্য ফাংশন যুক্ত করে না।
কৌতূহলী

Singletons যাহাই হউক না কেন একটি খারাপ অভ্যাস (গুগল "ক্ষতিকর Singleton" বলে মনে করা হয় এবং আপনার মত ফলাফল প্রচুর পাবেন এই আমি একজন antipattern বাস্তবায়ন একটি বৈশিষ্ট্য ব্যবহার করে যে বৈশিষ্ট্যের ভাল ব্যবহার বিবেচনা করা যেতে পারে মনে করি
weberc2

1

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

Point p;
cout << p;

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

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

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

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

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

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;
    }
}; 

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

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


1

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

ক্লাবহাউস

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{};

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

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

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


0

ক্লাসের জন্য ট্রি অ্যালগোরিদমগুলি প্রয়োগ করার সময়, প্রোফাইমার আমাদের যে ফ্রেমওয়ার্ক কোডটি দিয়েছিলেন তাতে নোড ক্লাসের বন্ধু হিসাবে ট্রি ক্লাস ছিল।

এটি কোনও সেটিং ফাংশনটি ব্যবহার না করেই আপনাকে সদস্য ভেরিয়েবল অ্যাক্সেস করতে দেওয়া ছাড়া সত্যই কোনও ভাল কাজ করে না।


0

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

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

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;
}

0

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


-1

আপনি পারে কঠিন এবং খাঁটি গলি নীতিগুলো মেনে চলে এবং নিশ্চিত যে এমনকি যেকোনো শ্রেণী পর্যন্ত কোনো ডেটা সদস্যদের accessors যাতে সমস্ত বস্তু নয় শুধুমাত্র বেশী যে একমাত্র উপায় তাদের কাজ করার জন্য তাদের তথ্য সম্পর্কে জানতে পারেন পরোক্ষ মাধ্যমে হতে বার্তা , অর্থাত্‍ পদ্ধতিগুলি।

এমনকি সি # এর অভ্যন্তরীণ দৃশ্যমানতা কীওয়ার্ড রয়েছে এবং জাভাতে কিছু জিনিসের জন্য এটির ডিফল্ট প্যাকেজ স্তরের অ্যাক্সেসযোগ্যতা রয়েছে। সি ++ আসলে গলি আদর্শ কাছাকাছি minimizinbg দ্বারা নির্দিষ্ট করে একটি বর্গ মধ্যে দৃশ্যমানতা এর আপস আসে ঠিক যা অন্যান্য শ্রেণী এবং শুধুমাত্র অন্য ক্লাসের তা দেখতে পারে।

আমি আসলে সি ++ ব্যবহার করি না তবে সি # এর যদি বন্ধু থাকে তবে আমি সমাবেশ-গ্লোবাল অভ্যন্তরীণ পরিবর্তে এটিই করতাম সংশোধকটির পারি, যা আমি আসলে অনেক বেশি ব্যবহার করি। এটি প্রকৃতপক্ষে ইনপ্যাপুলেশন ভাঙবে না, কারণ .NET মোতায়েনের এককটি একটি সমাবেশ।

তবে তারপরে ইন্টারনালভিসিবলিটো অ্যাট্রিবিউট (অন্যান্যঅ্যাসাব্যাস) রয়েছে যা ক্রস-অ্যাসেম্বলি বন্ধু ব্যবস্থার মতো কাজ করে। মাইক্রোসফ্ট ভিজ্যুয়াল ডিজাইনার অ্যাসেমব্লির জন্য এটি ব্যবহার করে ।


-1

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

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;
}

যে বিষয়গুলি স্ট্রিম স্ট্রিমটি দেখায় না সেগুলি লুকিয়ে রাখা সহজ হয়ে যায়।


1
ইন্টারফেসগুলি কি এটি অর্জনের জন্য একটি পরিষ্কার উপায় হবে না? কেউ কি MyFooPrivate.h সন্ধান বন্ধ করবেন?
জেবিআরওয়িলকিনসন

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

আপনি পিআইএমপিএল আইডিয়ামটি উল্লেখ করছেন; আপনি যে মনে করছেন বলে মনে হচ্ছে অতিরিক্ত এনক্যাপসুলেশন নয় সেই উদ্দেশ্যে, কিন্তু প্রয়োগের বিশদটি শিরোনামের বাইরে সরিয়ে নিয়ে যাওয়া যাতে একটি বাস্তবায়নের বিশদ পরিবর্তন করা ক্লায়েন্ট কোডের পুনঃনির্মাণকে বাধ্য করে না। আরও, এই প্রতিমাটি প্রয়োগের জন্য বন্ধু ব্যবহার করার দরকার নেই।
weberc2

হ্যাঁ ঠিক. এর মূল উদ্দেশ্য বাস্তবায়ন বিশদটি সরিয়ে নেওয়া। সেখানে থাকা বন্ধুটি প্রাইভেট বা অন্য উপায়ে থেকে পাবলিক ক্লাসের ভিতরে ব্যক্তিগত সদস্যদের পরিচালনা করতে দরকারী handle
shash
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.