الوحدة الحادية عشر:::::من الدروس

محتويات الوحدة
 
التحميل الزائد للمؤثرات
مثال توضيحي للمؤثر(++)
كيفية ترجيع كائن
مثال توضيحي للمؤثر(--)
تحميل المؤثرات الثانوية
تحميل مؤثر الجمع(+)
تحميل مؤثر الأسناد المركب
تحميل مؤثر المقارنة
التحميل الزائد لمؤثر الإسناد
 
 
 
 
 
 
 
وحدات اخرى
 
  الوحدة الأولى
  الوحدة الثانية
  الوحدة الثالثة
  الوحدة الرابعة
  الوحدة الخامسة
  الوحدة السادسة
  الوحدة السابعة
  الوحدة الثامنة
  الوحدة التاسعة
  الوحدة العاشرة
  الوحدة الحادية عشر
  الوحدة الثـانية عشر
  الوحدة الثالثة عشر
  الوحدة الرابعة عشر
 

 مواقع أخرى

 

الأخبار

 
  الجزيرة
  العربية

  BBC عربي

  CNN عربي

 

الصحف

 

  الحياة
  الوطن
  القدس العربي
  الشرق الأوسط

 

 الجامعات

 
  جامعة أم القرى
  جامعة الملك فهد

  جامعة الملك سعود

  جامعة الملك عبد العزيز  

 

الرياضة

 
  شبكة الزعيم
  منتديات مدريدي

 

 

 
 


الوحدة الحادية عشر

   

التحميل الزائد للمؤثرات

Operators Over Loading

 

تعريف التحميل الزائد للمؤثرات

 Definition Operators Over Loading 

    هو المقدرة على ربط مؤثر معين بدالة عضو في صنف ويتم استدعاؤها عند تطبيق المؤثر على أحد كائنات الصنف .

فائدة التحميل الزائد للمؤثرات :-

استخدام الطريقة أو الأسلوب المستخدم في التعامل مع الأنواع المعرفة مسبقاً ( الأنواع الأساسية ) في التعامل مع الأنواع المعرفة من قبل المستخدم ( الكائنات ) مثلاً : يمكن أن نقوم بتطبيق المؤثر الرياضي ( + ) [ مؤثر الجمع ] على عددين صحيحين أو حقيقيين   ( أنوع أساسية ) ولكن لا يمكن أن نطبق هذا المؤثر على كائنين     ( أنواع معرفة ) إلا بعد تحميل المؤثر( +) تحميلاً زائداً .

شروط التحميل الزائد للمؤثرات :-

1ـ لا ينبغي تغيير وظيفة المؤثر عند التحميل مثلاً إذا قمنا بتحميل المؤثر ( + ) تحميلاً زائداً فلا ينبغي أن تستخدمه في أجراء عملية أخرى مثل ( -  أو * ........ الخ )  .

2ـ لا ينبغي تغيير أولوية المؤثر عند التحميل  .

المؤثرات التي يتم تحميلها هي :-

المؤثرات الأحادية 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

alpha1.display ( ) ;

alpha2.display ( ) ;

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 ;

b1.display( );

++b2 ;

b2.display( );

beta b3 ;

b3 = ++b1 ;

b3.display( ) ;

b3 = ++b2 ;

b3.display( ) ;

getch();

}

المخرجات (( Output ))

1

20

2

21

3

22

 
 

 أعلى

 

 

   
 كيفية ترجيع كائن

  يمكن لدالة التحميل الزائد أن ترجع كائن بثلاث طرق :

1.باستخدام المؤشرthis كما في المثال السابق

alpha  alpha : : operator ++ (  )

{

++ a -> this ;

return  * this ;

}

2. باستخدام كائن مؤقت Temporary Object  

alpha  alpha :: operator ++ (  )

{

alpha  temp ;

temp .a  = ++ this->a;

return temp ;

}

3. باستخدام كائن من غير اسم Name Less Object

alpha  alpha : : operator ++ (  )

{

int  a1 = ++ this->a ;

return   a 1 ;

// or

// return    alpha  ( a 1)  ;

// كأننا استدعينا دالة البناء ذات الوسيطة الواحدة

}

 
 

 أعلى

 

 

   
مثال توضيحي المؤثر( -- )

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

b1.display( );

b2-- ;

b2.display( );

beta b3 ;

b3 = --b1 ;

b3.display( ) ;

b3 = --b2 ;

b3.display( ) ;

getch();

}

المخرجات (( Output ))

 

1

20

0

19

-1

18

 
 
 

 أعلى

 

 

   

 تحميل المؤثرات الرياضية الثنائية :-

    المؤثرات الثنائية هي :

ü    مؤثر الجمع( + )

ü    مؤثر الطرح ( - )

ü    مؤثر الضرب ( * )

ü    مؤثر القسمة  ( / )

ü    مؤثر باقي القسمة ( % )

دائماً في تحميل المؤثرات الرياضية الثنائية لا بد من وجود قيمة راجعة ( كائن ) .

حيث يجب أن ترجع الدالة العضو المربوطة بالمؤثر كائن معين.
 
 

 أعلى

 

 

   
 تحميل مؤثر الجمع (+)

مثال :-

برنامج يقوم بإجراء عملية الجمع ( + ) على كائنين :

#include<iostream.h>

#include<conio.h>

class  add

{

private:

int a  ;

public:

add( )

{

int a1 = 1 ;

a = a1 ;

}

add ( int) ;

void display ( ) ;

add operator + ( add ) ;

} ;

add :: add ( int  a1 )

{

this -> a = a1 ;

}

void add :: display( )

{

cout << a <<  "\n" ;

}

add  add :: operator + ( add p1 )

{

add temp ;

temp.a = this -> a + p1.a ;

return temp ;

}

main ( )

{

int x ;

cout << "Enter x   :" ;

cin>> x;

add   add1 , add2( x ) ;

add1.display( );

add2.display( ) ;

add   add3 ;

add3 = add1 + add2 ;

add3.display( );

getch( ) ;

}

المخرجات (( Output ))

1

قيمة x

1+  قيمة x

ملاحظه : -

يمكن تطبيق هذا المثال على كافة المؤثر الرياضية الثنائية الأخرى فقط نغير فقط نوع المؤثر .

 
 

 أعلى

 

 

   

تحميل مؤثر الإسناد المركب:-

 مؤثرات الإسناد المركب هي :

= % , = /    ,    = * ,   = -   ,  = +

سوف نقوم بتحميل هذه المؤثرات حتى نستطيع استخدامها مع الكائنات

مثال يوضح تحميل المؤثر =+

صنف الأمتار :

·خصائص الصنف :-

float meter                                             

·العمليات ( الدوال ) :-

1)    دالة بناء افتراضية ( بدون وسائط ) .

2)     دالة بناء ذات وسيطة واحدة .

3)    دالة طباعة الأمتار .

4)    دالة تحميل المؤثر = + .

 

نص البرنامج :-

#include<iostream.h>

#include<conio.h>

class meters

{

private :

float m ;

public :

meters ( )

{

m = 0.0  ;

}

meters(float  m1 )

{

m = m1 ;

}

void show ( )

{

cout<< m << "\n" ;

}

meters operator += ( meters m1 )

{

//First Metods

this ->  m +=  m1.m ;

return * this ;

//Second Methods

//meters temp ;

//temp.m += m1.m ;

//return temp ;

// Third Methods

//float mm ;

//mm += m1.m ;

//return (mm);

// or

// return meter (mm) ;

}

} ;

main ( )

{

meters m1 , m2 ( 12.5 ) ;

meters m3 ( m2 ) ;

m1.show( );

m2.show() ;

m3.show() ;

m1 += m2 ;

m1.show() ;

m2 += m3  ;

m2.show() ;

getch() ;

}

المخرجات (( Output ))

0. 0

12. 5

12. 5

12. 5

25

ملاحظة :-

 يمكن تطبيق مؤثرات الإسناد المركب الأخرى

=% و = / و = * و = -

 فقط نقوم بتغيير نوع المؤثر .
 

 

 

 أعلى

 

 

   
تحميل مؤثرات المقارنة :-

  Over loading comparison operator

     مؤثرات المقارنة هي  :-

=!  ,    ==  ,   =>   ,   =<    ,  >  ,    <

ملاحظة : مؤثرا ت المقارنة دائماً ترجع قيمة منطقية إذا تحقق الشرط ترجع  true  

وإذا لم يتحقق  ترجع false

مثال :

 يوضح تحميل مؤثر المقارنة أكبر من grater than " < "

#include<iostream.h>

#include<conio.h>

class    comp

{

private :

int     a;

public :

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 ;

}

} ;

main ( )

{

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

getch() ;

}

ملاحظة :-

 يمكن تطبيق هذا المثال على مؤثرات المقارنة الأخرى .

 
 

 أعلى

 

 

   
التحميل الزائد لمؤثر الإسناد ( = ): 

 

    نستخدم التحميل الزائد للمؤثر (= ) في الحجز الديناميكي لأنه عادة ما يسبب خطأ أما في غير          الحجز الديناميكي لا يحدث خطأ .

    عندما يتم إسناد كائن إلى كائن أخر مثلاً n1   = n2   فإن المترجم سوف يقوم بنسخ محتويات

    ( بيانات ) الكائن من المصدر n2 إلى كائن المستودع n1 .

عملية الإسناد n1   = n2  إن لم تكن هناك ذاكرة محجوزة فلا تحدث مشكلة تظهر المشكلة مع هذا المؤثر ( =) عندما يتم استخدامه مع كائنات تحوي ذاكرة محجوزة ديناميكياً ( أي أن بعض متغيرات الصنف عبارة عن مؤشرات )

مثال :-

إذا كان لدينا كائنين يحتويان على مؤشرات حرفية ( سلاسل )

الكائن الأول

الكائن الثاني

S1

S2

السلسلة str

السلسلة str

طولها n

طولها 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<iostream.h>

#include<conio.h>

#include<string.h>

class           string

{

private :

char * str;

public :

          دالة بناء افتراضية //

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 ;

}

void display ( )

{

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

return  * this ;

}

}   ;

main ( )

{

string  s1 ( "hello " ) ,  s2 ( " world " );

s1- display ( ) ;

s2- display ( ) ;

s2= s1;       //  s1( s2);

s2-display (  ) ;

getch( ) ;

}

 
  << الوحدة السابقة

 أعلى

الوحدة التالية >>

 

                                                             

 
   
 

جميع الحقوق محفوظة © 2006