PDA

View Full Version : چه روش هایی برای ارتباط میان دو کلاس وجود دارد؟



soroush_vs
چهارشنبه 03 تیر 1388, 14:14 عصر
با سلام،
دوستان چه روش هایی برای ارتباط میان دو کلاس وجود دارد؟
مشکل من این است که میخواهم از داخل یک کلاس مثلا یک تابع از کلاس دیگر را فراخوانی کنم.
مایل هستم که تمامی راه ها را بدانم تا علاوه بر یادگیری تمامی آنها ، بسته به شرایطم یکی را انتخاب نمایم.
متشکرم.

PC2st
چهارشنبه 03 تیر 1388, 16:23 عصر
روش‌های متفاوتی می‌توان به کار برد، در کل برای سطوح دسترسی برای اعضای کلاس‌ها، به فرض اگر کلاس‌های زیر را تعریف کرده باشیم:


class A
{
friend class I_friend_A;
friend class J_friend_and_is_A;
private: void private_print_of_A () { }
protected: void protected_print_of_A () { }
public: void public_print_of_A () { }
};

class B_has_A
{
private: A _a;
//private: void private_print_of_B () { _a.private_print_of_A (); }
//protected: void protected_print_of_B () { _a.protected_print_of_A (); }
public: void public_print_of_B () { _a.public_print_of_A (); }
};

class C_is_A : public A //most used inheritance type
{
//private: void private_print_of_C () { private_print_of_A (); }
protected: void protected_print_of_C () { protected_print_of_A (); }
public: void public_print_of_C () { public_print_of_A (); }
};

class D_is_A : protected A //protected inheritance type
{
//private: void private_print_of_D () { private_print_of_A (); }
protected: void protected_print_of_D () { protected_print_of_A (); }
public: void public_print_of_D () { public_print_of_A (); }
};

class E_is_A : private A //default behavior
{
//private: void private_print_of_D () { private_print_of_A (); }
protected: void protected_print_of_D () { protected_print_of_A (); }
public: void public_print_of_D () { public_print_of_A (); }
};

class F_is_C_is_A : public C_is_A
{
//private: void private_print_of_F () { private_print_of_A (); }
protected: void protected_print_of_F () { protected_print_of_A (); }
public: void public_print_of_F () { public_print_of_A (); }
};

class G_is_D_is_A : public D_is_A
{
//private: void private_print_of_G () { private_print_of_A (); }
protected: void protected_print_of_G () { protected_print_of_A (); }
public: void public_print_of_G () { public_print_of_A (); /*protected call*/ }
};

class H_is_E_is_A : public E_is_A
{
//private: void private_print_of_H () { private_print_of_A (); }
//protected: void protected_print_of_H () { protected_print_of_A (); }
//public: void public_print_of_H () { public_print_of_A (); }
};

class I_friend_A
{
private: A _a;
private: void private_print_of_I () { _a.private_print_of_A (); }
protected: void protected_print_of_I () { _a.protected_print_of_A (); }
public: void public_print_of_I () { _a.public_print_of_A (); }
};

class J_friend_and_is_A : A //default is private inheritance
{
private: void private_print_of_J () { private_print_of_A (); }
protected: void protected_print_of_J () { protected_print_of_A (); }
public: void public_print_of_J () { public_print_of_A (); }
};
خطوط یا اعضایی که بصورت comment در آورده شده‌اند، در واقع اشتباه بوده و خطا تولید خواهند کرد.
کلاس A شامل سه تابع که یکی private و یکی protected و یکی public هستند، که کلاس A بعنوان دوست کلاس‌های I_friend_A و J_friend_and_is_A می‌باشد.
کلاس B_has_A شامل یک شیي از نوع A می‌باشد، پس می‌توان گفت که کلاس‌های A و B_has_A به نسبت هم غریبه هستند. پس کلاس B_has_A فقط می‌تواند به اعضای public کلاس A دسترسی داشته باشد.
کلاس C_is_A که از کلاس A به ارث برده است، پس به اعضای private دسترسی ندارد. کلاس‌های D_is_A و E_is_A نیز مشابه همین حالت را دارند با این تفاوت که سطح دسترسی اعضای کلاس A را تغییر داده‌اند. در کلاس C_is_A تغییری نمی‌کند اما در کلاس D_is_A تمام اعضای public کلاس A بعنوان protected تغییر می‌یابند و در کلاس E_is_A تمام اعضای protected و public کلاس A بصورت private تغییر می‌یابند پس اگر کلاسی بخواهید از کلاس‌های D_is_A و E_is_A به ارث ببرد، با شرایط جدیدی روبرو خواهد شد.
کلاس F_is_C_is_A هم که از C به ارث رسیده و بطور غیر مستقیم یکی از وارثان کلاس A به حساب می‌آید.
در کلاس G_is_D_is_A چون کلاس D_is_A شرایط دسترسی به اعضای کلاس A را محدود به protected کرده است، پس متد public_print_of_A بصورت protected در کلاس G_is_D_is_A فراخوانی می‌شود.
در کلاس H_is_D_is_A چون کلاس E_is_A شرایط دسترسی به اعضای کلاس A را محدود به private کرده است، پس متد public_print_of_A و protected_print_of_A بعنوان private تلقی شده و نمی‌توان آنها را همچون تابع private_print_of_A فراخوانی کرد.
کلاس I_friend_A هم چون دوست کلاس A است، پس می‌تواند به تمام اعضای آن از جمله private نیز دسترسی داشته باشد.
کلاس J_friend_and_is_A هم دوست کلاس A و هم از آن به ارث برده است، و مثل حالت قبل می‌تواند به اعضای private دسترسی داشته باشد.
فقط در استفاده از ارث بری بطور protected یا private (مثل کلاس‌های D_is_A و E_is_A) توجه داشته باشید که عمل downcast (تبدیل یک شیي فرزند به والد) امکان ناپذیر خواهد شد. بطور مثال:


int main ()
{
D_is_A* hea = new D_is_A ();
A* a = dynamic_cast <A*> (hea); //ERROR A is an inaccessible base of D_is_A
}

PC2st
چهارشنبه 03 تیر 1388, 19:59 عصر
البته اینم بگم تا کمی کاملتر بشه، یک حالت هم برای کلاسهای تو در تو (Nested Classes) هست:


class Outer
{
class Inner
{
Outer* _outer; //Outer Object Pointer

public:
Inner (Outer* __outer) : _outer (__outer) { } //Inner Construction
};

Inner _inner; //Inner Object Instance

public:
Outer () : _inner (this) { } //Outer Construction
};
در اینصورت، کلاس Inner (از طریق اشاره‌گر outerـ) توانایی استفاده از اعضای private و protected کلاس Outer رو داره، فقط باید شیي this از کلاس Outer به طریقی بتونه به کلاس داخلی Inner فرستاده بشه.
معمولا زمانی از کلاس‌های تو در تو استفاده میشه که کلاس داخلی به نوعی فقط منحصرا به کلاس خارجی‌اش تعلق داشته باشه.