مواقع أخرى
الأخبار
BBC عربي
CNN عربي
الصحف
الجامعات
جامعة الملك سعود
جامعة الملك عبد العزيز
الرياضة
التحميل الزائد للمؤثرات
Operators Over Loading
تعريف التحميل الزائد للمؤثرات
Definition Operators Over Loading
هو المقدرة على ربط مؤثر معين بدالة عضو في صنف ويتم استدعاؤها عند تطبيق المؤثر على أحد كائنات الصنف .
فائدة التحميل الزائد للمؤثرات :-
استخدام الطريقة أو الأسلوب المستخدم في التعامل مع الأنواع المعرفة مسبقاً ( الأنواع الأساسية ) في التعامل مع الأنواع المعرفة من قبل المستخدم ( الكائنات ) مثلاً : يمكن أن نقوم بتطبيق المؤثر الرياضي ( + ) [ مؤثر الجمع ] على عددين صحيحين أو حقيقيين ( أنوع أساسية ) ولكن لا يمكن أن نطبق هذا المؤثر على كائنين ( أنواع معرفة ) إلا بعد تحميل المؤثر( +) تحميلاً زائداً .
شروط التحميل الزائد للمؤثرات :-
1ـ لا ينبغي تغيير وظيفة المؤثر عند التحميل مثلاً إذا قمنا بتحميل المؤثر ( + ) تحميلاً زائداً فلا ينبغي أن تستخدمه في أجراء عملية أخرى مثل ( - أو * ........ الخ ) .
2ـ لا ينبغي تغيير أولوية المؤثر عند التحميل .
المؤثرات التي يتم تحميلها هي :-
1ـ المؤثرات الأحادية Uniary Operators .
المؤثرات الأحادية هي :-
أ ـ مؤثر التزايد ( ++) Increment .
ب ـ مؤثرات التناقص (--) Decrement .
فمثلاً :
يقوم المؤثر(+) بجمع رقمين و التحميل الزائد لمؤثر الجمع يمكن أن يحقق مثلا جمع بيانات كائنين شروط التحميل الزائد للمؤثرات:-
1- لا ينبغي تغيير وظيفة المؤثر عند التحميل .
مثلاً : إذا قمنا بتحميل المؤثر (+) تحميلاً زائداً فلا ينبغي أن نستخدمه في إجراء عملية أخرى
مثل ( - أو * ..... الخ)
2- لا ينبغي تغيير ترتيب أولوية المؤثر عند التحميل.
الصيغة العامة لدالة التحميل الزائد:-
Data_ type Class_Name :: Operator (arg-List)
{
// statements
}
حيث:
Data_ type
نوع القيمة التي ترجعها الدالة
Class-Name
اسم الصنف التابعة له الدالة
Operator
كلمه محجوزة للإشارة إلى أن هذه الدالة دالة مؤثر
arg-List
معاملات الدالة
statements
تعليمات الدالة
أعلى
class alpha
private :
int a ;
public :
alpha ( )
int a1 = 1 ;
a = a1;
void display ( ) ;
void operator ++ ( ) ;
alpha ( int );
} ;
alpha :: alpha ( int a1 )
this -> a = a1 ;
void alpha :: display ( )
cout << a << "\n" ;
الآن نكتب تفاصيل الدالة operator ++ ( ) مع ملاحظة أن الربط بين المؤثر والدالة العضو يتم باستخدام الكلمة المحجوزة operator مع المؤثر المراد استخدامه وهو ( ++)
void alpha : : operator ++ ( )
this -> a = this -> a + 1;
// ++ this –> a ;
تكملة البرنامج ( الدالة main ) هي :
main ( )
alpha alpha1 , alpha2( 10 ) ;
alpha1.display ( ) ;
alpha2.display ( ) ;
++ alpha1;
++ alpha2;
//لاحظ استخدمنا المؤثر ++ مع الكائنات
// لأننا قمنا بتحميله تحميلاً زائداً alpha1 و alpha2
getch ( ) ;
لاحظ :- مخرج البرنامج هو :
وبنفس الطريقة نستطيع أن نستخدم المؤثر الأحادي ( -- ) في البرنامج السابق فقط بتغيـــير ( ++ ) إلى ( -- ) .
ملاحظة : في المثال السابق نستطيع أن نكتب مثل العبارات التالية
++ alpha1 ;
++ alpha2 ;
ولكن لا نستطيع أن نكتب العبارة :
alpha1 = ++ alpha2;
وذلك لأن دالة التحميل الزائد ليس لها مردود لا ترجع قيمة ( void ) وللقيام بهذه العملية يجب إعادة تعريف الدالة لكي ترجع قيمته والقيمة هي عبارة عن كائن يتم إسنادها إلى متغير على يسار مؤثر الإسناد ( = ) .
إذن سوف تكون دالة التحميل الزائد على الصورة التالية :
alpha alpha :: operator ++ ( )
++ this -> a ;
return * this ;
لاحظ :-
1. جعلنا الدالة ( )operator ++ من نوع الصنف alpha .
2. وضعنا ( *) مع المؤشر this لأننا نريد إرجاع محتوى المؤشر this
والآن نكتب البرنامج بصورة متكاملة لإرجاع كائن من دالة التحميل الزائد :
#include<iostream.h>
#include<conio.h>
class beta
private:
int b ;
public:
beta()
b = 1 ;
beta(int) ;
void display( ) ;
beta operator ++ ( ) ;
};
beta::beta( int b1 )
b = b1 ;
beta beta :: operator ++( )
int b1 ;
b1 = ++ this -> b ;
return b1 ;
void beta::display( )
cout<< b << "\n" ;
main( )
beta b1 , b2(20);
b1.display( );
b2.display( );
++b1 ;
++b2 ;
beta b3 ;
b3 = ++b1 ;
b3.display( ) ;
b3 = ++b2 ;
getch();
المخرجات (( Output ))
1
20
2
21
3
22
يمكن لدالة التحميل الزائد أن ترجع كائن بثلاث طرق :
1.باستخدام المؤشرthis كما في المثال السابق
alpha alpha : : operator ++ ( )
++ a -> this ;
2. باستخدام كائن مؤقت Temporary Object
alpha temp ;
temp .a = ++ this->a;
return temp ;
3. باستخدام كائن من غير اسم Name Less Object
int a1 = ++ this->a ;
return a 1 ;
// or
// return alpha ( a 1) ;
// كأننا استدعينا دالة البناء ذات الوسيطة الواحدة
beta operator -- ( ) ;
beta beta :: operator --( )
b1 = -- this -> b ;
--b1 ;
b2-- ;
b3 = --b1 ;
b3 = --b2 ;
0
19
-1
18
تحميل المؤثرات الرياضية الثنائية :-
المؤثرات الثنائية هي :
ü مؤثر الجمع( + )
ü مؤثر الطرح ( - )
ü مؤثر الضرب ( * )
ü مؤثر القسمة ( / )
ü مؤثر باقي القسمة ( % )
دائماً في تحميل المؤثرات الرياضية الثنائية لا بد من وجود قيمة راجعة ( كائن ) .
مثال :-
برنامج يقوم بإجراء عملية الجمع ( + ) على كائنين :
class add
add( )
a = a1 ;
add ( int) ;
add operator + ( add ) ;
add :: add ( int a1 )
void add :: display( )
add add :: operator + ( add p1 )
add temp ;
temp.a = this -> a + p1.a ;
int x ;
cout << "Enter x :" ;
cin>> x;
add add1 , add2( x ) ;
add1.display( );
add2.display( ) ;
add add3 ;
add3 = add1 + add2 ;
add3.display( );
getch( ) ;
قيمة x
1+ قيمة x
ملاحظه : -
يمكن تطبيق هذا المثال على كافة المؤثر الرياضية الثنائية الأخرى فقط نغير فقط نوع المؤثر .
تحميل مؤثر الإسناد المركب:-
مؤثرات الإسناد المركب هي :
= % , = / , = * , = - , = +
سوف نقوم بتحميل هذه المؤثرات حتى نستطيع استخدامها مع الكائنات
مثال يوضح تحميل المؤثر =+
صنف الأمتار :
·خصائص الصنف :-
float meter
·العمليات ( الدوال ) :-
1) دالة بناء افتراضية ( بدون وسائط ) .
2) دالة بناء ذات وسيطة واحدة .
3) دالة طباعة الأمتار .
4) دالة تحميل المؤثر = + .
نص البرنامج :-
class meters
float m ;
meters ( )
m = 0.0 ;
meters(float m1 )
m = m1 ;
void show ( )
cout<< m << "\n" ;
meters operator += ( meters m1 )
//First Metods
this -> m += m1.m ;
//Second Methods
//meters temp ;
//temp.m += m1.m ;
//return temp ;
// Third Methods
//float mm ;
//mm += m1.m ;
//return (mm);
// return meter (mm) ;
meters m1 , m2 ( 12.5 ) ;
meters m3 ( m2 ) ;
m1.show( );
m2.show() ;
m3.show() ;
m1 += m2 ;
m1.show() ;
m2 += m3 ;
getch() ;
0. 0
12. 5
25
ملاحظة :-
يمكن تطبيق مؤثرات الإسناد المركب الأخرى
=% و = / و = * و = -
Over loading comparison operator
مؤثرات المقارنة هي :-
=! , == , => , =< , > , <
ملاحظة : مؤثرا ت المقارنة دائماً ترجع قيمة منطقية إذا تحقق الشرط ترجع true
وإذا لم يتحقق ترجع false
مثال :
يوضح تحميل مؤثر المقارنة أكبر من grater than " < "
class comp
int a;
comp ( int n )
a = n ;
void display ( )
cout << a << "/n" ;
bool operator > ( comp c1 )
// or Another Methods
// void operator > ( comp c1 )
return this -> a > c1.a ;
int x , y;
cout <<"Enter x : " ;
cin >> x ;
cout <<"Enter y : " ;
cin >> y ;
comp c1( x ) , c2( y) ;
if ( c1 > c2 )
cout << " c1 is greater " ;
else
cout << " c2 is greater " ;
يمكن تطبيق هذا المثال على مؤثرات المقارنة الأخرى .
نستخدم التحميل الزائد للمؤثر (= ) في الحجز الديناميكي لأنه عادة ما يسبب خطأ أما في غير الحجز الديناميكي لا يحدث خطأ .
عندما يتم إسناد كائن إلى كائن أخر مثلاً n1 = n2 فإن المترجم سوف يقوم بنسخ محتويات
( بيانات ) الكائن من المصدر n2 إلى كائن المستودع n1 .
عملية الإسناد n1 = n2 إن لم تكن هناك ذاكرة محجوزة فلا تحدث مشكلة تظهر المشكلة مع هذا المؤثر ( =) عندما يتم استخدامه مع كائنات تحوي ذاكرة محجوزة ديناميكياً ( أي أن بعض متغيرات الصنف عبارة عن مؤشرات )
إذا كان لدينا كائنين يحتويان على مؤشرات حرفية ( سلاسل )
الكائن الأول
الكائن الثاني
S1
S2
السلسلة str
طولها n
إذا تم تعيين السلسلة " hello" للكائن s1 الذي يحدث في هذه الحالة .
1- يتم حجز ذاكرة لستة مواقع ( 5 بعدد حروف السلسلة + حرف الانتهاء الخاص \0 )
إذن طول السلسلة 5 وهو عدد الحروف فقط
عنوان موقع السلسلة في الذاكر ة Str = 0x00A5
إذا كتبنا الأمر التالي s2 = s1 ;
سيكون الكائن s2 على النحو التالي
طول السلسلة للكائن s2 خمسة أحرف عنوان السلسلة Str = 0x00A5
فكان الكائنين يشيرون إلى نفس الموقع " hello "
وعند انتهاء البرنامج يتم تنفيذ الآتي :
1. يتم استدعاء دالة الهدم للكائن الأول حيث سيتم مسح للذاكرة التي يشير إليها المؤشر Str التابع لـ s1 .
2. يتم استدعاء دالة الهدم للكائن الثاني حيث سيتم حذف الذاكرة التي يشير إليها المؤشر Str التابع لـ s2 ولكن سوف يحدث خطأ لعدم وجود ذاكرة تشير إليها Str التابع لـ s2 لأنها حذفت بواسطة Str التابع لـ S1 إذن المشكلة هي في عملية الإسناد s1= s2 .
ولحل هذه المشكلة يتم تحميل المؤثر = بشكل زائد
مثال يوضح حل مشكلة الإسناد السابقة :-
#include<string.h>
class string
char * str;
دالة بناء افتراضية //
string ( )
str= " " ;
دالة بناء ذات وسيطة والوسيطة عبارة عن مؤشر //
string ( char * s )
int n = strlen ( s ) ;
str = new char [n+1];
strcpy ( str , s ) ;
كائن دالة بناء ناسخة //
string ( const string & s )
{ int n = strlen ( s.str ) ;
str = new char [ n+1] ;
strcpy ( str, s.str) ;
~ string ()
delete [ ] str ;
cout << this -> str << " \ n " ;
string operator = ( string s )
أولاً تسمح بتغيير المستودع //
delete [ ] this -> str ;
نحدد طول المتغير لنسخة //
Int n = strlen ( s.str ) ;
نحجز ذاكرة الكائن المستودع //
this -> str = new char [ n + 1 ] ;
نسخ من الهدف ( المصدر إلى المستودع //
strcpy ( str , s.str ) ;
string s1 ( "hello " ) , s2 ( " world " );
s1- display ( ) ;
s2- display ( ) ;
s2= s1; // s1( s2);
s2-display ( ) ;
الوحدة التالية >>
جميع الحقوق محفوظة © 2006