منبع :
http://www.aachp.ir/post.aspx?no=72
-----------------------------------------------
توابع دوست کلاس - ارائه شده توسط مسعود اقدسی فام
توابع دوست کلاسها از جمله موارد بحث برانگیز برنامه نویسی شی گرا به زبان ++C هستن. چرا که یکی از اصول اساسی شی گرایی (یعنی پنهان سازی اطلاعات) رو نقض می کنن! با این وجود به خاطر کاربردهای متعددی که دارن از حضورشون نمی شه چشم پوشی کرد.
به زبان ساده، توابع دوست یک کلاس توابعی هستن که عضو کلاس نیستن، اما به تمامی داده ها و توابع خصوصی و محافظت شده اون دسترسی دارن!! یه مثال ساده می زنم:
کد:
class myclass
{
friend void print_a ( myclass ) ;
private:
unsigned a ;
public:
myclass ( int r )
{
a = r > 0 ? r : - r ;
}
void print ( )
{
cout << a ;
}
};
void print_a ( myclass ob )
{
cout << ob.a ;
}
void main()
{
myclass ob ( 9 ) ;
ob.print ( ) ;
cout << "\t" ;
print_a ( ob ) ;
}
خروجی برنامه به این صورته:
تابع دوست print_a علیرغم اینکه عضو کلاس myclass نیست اما به عضو خصوصی a از کلاس دسترسی داره.
این قطعه برنامه خیلی ساده روش استفاده از توابع دوست رو نشون می ده. توابع دوست با کلمه کلیدی friend در ابتدای تعریفشون مشخص می شن. توجه داشته باشید که چون این توابع عضو کلاس نیستن نباید عملگر تعیین حوزه ( :: ) زمان تعریف بلوک بدنه اونها استفاده بشه. یعنی این عبارت نادرسته:
کد:
void myclass::print_a ( myclass ob )
چرا که ممکنه یه تابع مشخص، تابع دوست برای چندین کلاس مختلف باشه. درضمن بلوک بدنه این توابع باید بیرون از تعاریف هر کلاسی نوشته بشه.
اما چرا به توابع دوست نیاز داریم؟ چه کاربردهایی دارن که علیرغم نقض آشکار قوانین شی گرایی ازشون استفاده می شه؟ یکی از کاربردهای این توابع رو در ادامه بررسی می کنیم.
سربارگذاری عملگرها با توابع دوست:
قبلا در مورد سربازگذاری عملگرها در زبان ++C مطالبی ارائه شده. در این مطالب تاکید شده بود که برای عملگرهای دودویی (مثل جمع و ضرب و . . . ) شی سمت چپ تابع عملگر مربوطه رو فراخوانی می کنه و شی سمت راست به عنوان آرگومان به تابع ارسال می شه. مثلا اگه عملگر + برای کلاسی سربارگذاری شده باشه، دو عبارت زیر معادل هم هستن:
کد:
ob1 + ob2 ≡ ob1.operator+( ob2 )
حالا فرض کنید کلاسی برای کار با اعداد مختلط با نام comp تعریف کردیم. عملگر + هم مطابق با عمل جمع اعداد مختلط براش تعریف شده. برای جمع زدن یه عدد حقیقی (مثلا double) با یه عدد مختلط از تابع + بصورت زیر استفاده می کنیم:
کد:
comp operator + ( double f )
اما این تابع تنها برای جمع عدد حقیقی از سمت راست کاربرد داره، و نمی تونه از سمت چپ عدد حقیقی رو با عدد مختلط جمع کنه. به عنوان نمونه برای یه عدد مختلط مثل c تابع بالا عبارت c + 3.5 رو به خوبی محاسبه می کنه، اما اگه جای دو عملوند عوض بشه دیگه کاری از دستش بر نمی یاد! چرا که در این حالت شی سمت چپ از جنس خود کلاس نخواهد بود.
اینجاست که تابع دوست به کمک ما می یاد. به تعریف زیر دقت کنید:
کد:
friend comp operator + ( double f , comp c )
زمانی که از توابع دوست برای سربارگذاری عملگرهای دودویی استفاده می شه بر خلاف حالت اصلی هر دو شی به صورت آرگومان به تابع ارسال می شن. آرگومان اول شی سمت چپ و آرگومان دوم شی سمت راست رو مشخص می کنه. با تعریف بالا براحتی عبارت زیر هم محاسبه می شه:
کد کامل این کلاس به این صورت خواهد بود:
کد:
class comp
{
friend comp operator + ( double , comp ) ;
private:
double real , imag ;
public:
comp ( double r , double i )
{
real = r ;
imag = i ;
}
comp operator + ( comp r )
{
comp temp ( real + r.real , imag + r.imag ) ;
return temp ;
}
comp operator + ( double r )
{
comp temp ( real + r , imag ) ;
return temp ;
}
};
comp operator + ( double l , comp r )
{
comp temp ( l + r.real , r.imag ) ;
return temp ;
}
توجه داشته باشید که این تعریف برای کلاس اعداد مختلط به هیچ وجه کامل نیست و تنها قسمت کوچیکی از اون رو نشون می ده. البته خود زبان ++C هم برای کار با اعداد مختلط توابع و کلاسهایی رو داره که همه نیازها رو برآورده می کنن.
و یه نکته مهم دیگه:
برای سربارگذاری عملگرهای جریان (یعنی >> و <<) چاره ای ندارید جز اینکه از توابع دوست استفاده کنید (چرا؟).