التوارث المتعدد في ++C

c

التوارث المتعدد

يمكن لفئة تشتق من أكثر من فئة أساسية , ويكون شكل التعريف كالتالي :

Class A

{

};

Class B

{

};

Class C : public A, public B

{

};

يسمي هذا التوارث بالتوارث المتعدد multiple .وكمثال علي هذا تصور أننا نريد أن نسجل الخبرة الدراسية للموظفين , وإنه قد سبق لنا أن وضعنا في برنامج أخر فئة student تقوم بتسجيل المعهد الدراسي ودرجة النجاح في مصفوفة تملأ وتقرأ عن طريق دالتين grtedu(), putedu() , وأننا نريد أن نضيف هذه الإمكانية لفئة الموظفين عن طريق التوارث المتعدد . ولنتصور أننا نريد أن نعطي هذه الإمكانية لفئة المدراء والباحثين فقط ( مخالفين المبادئ الديموقراطية )

سوف يكون الشكل العام للبرنامج بعد تعديله كالأتي :

Class student

{};

Class employee

{};

Class manager : private employee, private student

{};

Class scientist : private employee, private student

Class labout : public employee

{};

أما صياغته الكاملة فهي :

employ.cpp


 


// employ.cpp


// models employee database using inheritance


// UCS Laboratories


#include <iostream.h>


#include <conio.h>


 


const int LEN = 80;           // maximum length of names


 


class employee                // employee class


   {


   private:


      char name[LEN];         // employee name


      unsigned long number;   // employee number


   public:


      void getdata()


     {


     cout << "\n   Enter last name: "; cin >> name;


     cout << "   Enter number: ";      cin >> number;


     }


      void putdata()


     {


     cout << "\n   Name: " << name;


     cout << "\n   Number: " << number;


     }


   };


 


class manager : public employee     // management class


   {


   private:


      char title[LEN];  // "vice-president" etc.


      double dues;      // golf club dues


   public:


      void getdata()


     {


         employee::getdata();


     cout << "   Enter title: ";          cin >> title;


     cout << "   Enter golf club dues: "; cin >> dues;


     }


      void putdata()


     {


     employee::putdata();


     cout << "\n   Title: " << title;


     cout << "\n   Golf club dues: " << dues;


     }


   };


class scientist : public employee      // scientist class


   {


   private:


      int pubs;     // number of publications


   public:


      void getdata()


     {


     employee::getdata();


     cout << "   Enter number of pubs: "; cin >> pubs;


     }


      void putdata()


     {


     employee::putdata();


     cout << "\n   Number of publications: " << pubs;


     }


   };


 


class laborer : public employee        // laborer class


   {


   };


 


void main()


   {


   manager m1, m2;


   scientist s1;


   laborer l1;


 


   cout << endl;


   cout << "\nEnter data for manager 1";    // get data for


   m1.getdata();                            // several employees


 


   cout << "\nEnter data for manager 2";


   m2.getdata();


 


   cout << "\nEnter data for scientist 1";


   s1.getdata();


 


   cout << "\nEnter data for laborer 1";


   l1.getdata();


 


   cout << "\nData on manager 1";           // display data for


   m1.putdata();                            // several employees


 


   cout << "\nData on manager 2";


   m2.putdata();


 


   cout << "\nData on scientist 1";


   s1.putdata();


 


   cout << "\nData on laborer 1";


   l1.putdata();


   getche();


   }




أسلوب الاشتقاق



أعلن عن اشتقاق الفئتين manager, scientist اشتقاقا خاصا private حيث لن تحتاج أي منهما لدالة من دوال الفئة الأساسية , بعكس فئة labour والتي ليس لها دوال خاصة بها , فأعلن عن اشتقاقها عاما public .



البادئات في الاشتقاق المتعدد



ليس في هذا البرنامج إعلان عن بادئات , لننظر مثالا يستخدمها في التوارث المتعدد لنفرض أننا نحفظ بيانات مخزن للأخشاب , توجد فيه قطع الخشب بأطوال ومقاطع مختلفة ودرجة جودة متباينة , وتريد أن نحتفظ ببيانات عن عددها وسعرها . سوف نستخدم لإدخال هذه البيانات ثلاثة فئات , فئتان أساسيتان هما : type لإدخال المقاس والنوع و dimension لإدخال الطول بالأقدام والبوصات ثم فئة مشتقة من كليهما هي lumber تجمع البيانات السابقة ثم تدخل بيانين خاصين بها , السعر والكمية .






englmult.cpp


 


 


// englmult.cpp


// multiple inheritance with English Distances


// UCS Laboratories


#include <iostream.h>


#include <string.h>       // for strcpy()


#include <conio.h>


 


const int LEN = 40;       // maximum length of strings


 


class Type                // type of lumber


   {


   private:


      char dimensions[LEN];


      char grade[LEN];


   public:


      Type()                      // constructor (no args)


     { strcpy(dimensions, "N/A"); strcpy(grade, "N/A"); }


 


      Type(char di[], char gr[])  // constructor (two args)


     { strcpy(dimensions, di); strcpy(grade, gr); }


 


      void gettype()              // get type from user


     {


     cout << "   Enter nominal dimensions (2x4 etc.): ";


     cin >> dimensions;


     cout << "   Enter grade (rough, const, etc.): ";


     cin >> grade;


     }


      void showtype()             // display type


     {


     cout << "\n   Dimensions: " << dimensions;


     cout << "\n   Grade: " << grade;


     }


   };


 


class Distance                    // English Distance class


   {


   private:


      int feet;


      float inches;


   public:


      Distance()                  // constructor (no args)


     { feet = 0; inches = 0.0; }


      Distance(int ft, float in)  // constructor (two args)


     { feet = ft; inches = in; }


      void getdist()              // get length from user


     {


     cout << "   Enter feet: ";  cin >> feet;


     cout << "   Enter inches: ";  cin >> inches;


     }


      void showdist()             // display distance


     { cout  << feet << "\'-" << inches << '\"'; }


   };


 


class Lumber : public Type, public Distance


   {


   private:


      int quantity;                      // number of pieces


      float price;                       // price of each piece


   public:


      Lumber() : Type(), Distance()      // constructor (no args)


     { quantity = 0; price = 0.0; }


                     // constructor (6 args)


      Lumber( char di[], char gr[],      // args for Type


          int ft, float in,          // args for Distance


          int qu, float prc ) :      // our own args


          Type(di, gr),              // call Type constructor


          Distance(ft, in)           // call Distance constr


     {


     quantity = qu; price = prc;     // use our own args


     }


      void getlumber()


     {


     Type::gettype();


     Distance::getdist();


     cout << "   Enter quantity: "; cin >> quantity;


     cout << "   Enter price per piece: "; cin >> price;


     }


      void showlumber()


     {


     Type::showtype();


     cout << "\n   Length: ";


     Distance::showdist();


     cout << "\n   Price for " << quantity


          << " pieces: $" << price * quantity;


     }


   };


 


void main()


   {


   Lumber siding;                   // constructor (no args)


 


   cout << "\nSiding data:\n";


   siding.getlumber();              // get siding from user


 


                    // constructor (6 args)


   Lumber studs( "2x4", "const", 8, 0.0, 200, 4.45 );


 


                    // display lumber data


   cout << "\nSiding";  siding.showlumber();


   cout << "\nStuds";     studs.showlumber();


   getche();


   }




الخاصية الهامة الجديدة في هذا البرنامج هي استخدام البادئات في الفئة المشتقة lumber فالبادئة تستدعي البادئات المناسبة في كل من الفئتين type, distance .



فالبادئة عديمة المعامل في الفئة type تضع رمز N/A بمعني , غير متاح Not Available في حالة محاولة إظهار بيانات لنوع لم تدخل بياناته والبادئة في فئة Distance مألوفة لديك وتقوم بادئة الفئة باستدعائها بالأمر :



Lumber() : Type(), Distance()



وبالنسبة للبادئة متعددة المعاملات لدينا بادئة ذات معاملين للفئة الأولي :



Type (char di[], char gr[])



{strcpy(dimension, di); stecpy(grade, gr); }



لإدخال بيانات المقاس ودرجة الجودة . ولدينا بادئة للفئة الثانية لإدخال الطول مألوفة لديك وأيضا تستدعي البادئة الخاصة بالفئة المشتقة هاتين البادئتين لإدخال هذه البيانات , ثم بيانين إضافيين هما الكمية والسعر , في بادئة ذات ستة معاملات , علي النحو التالي :



Lumber( char di[], char gr[], لإدخال الطول والنوع



Int ft, float in, لإدخال المقاسات



Int qu, float prc,): لإدخال الكمية والسعر



Type (di, gr), استدعاء البادئة الأولي



Distance (ft, in ); استدعاء البادئة الثانية



{……..} إدخال بياني الفئة المشتقة



وكالعادة تستخدم النقطتان : لاستدعاء البادئات من الفئات الأساسية



البلبلة في التوارث المتعددة



قد يثير التوارث المتعدد العجيب من المشاكل , فهناك فئتان أساسيتان تحتويان علي دوال بنفس الاسم , بينما ليس للفئة المشتقة دالة بهذا الاسم فكيف يتعامل الكائن المشتق مع الدالة المقصودة ؟



تحل مثل هذه المشكلة باستخدام مؤثر النطاق “::”، علي النحو التالي مثلا بإفتراض أن الكائن objC كائن منتم للفئة C المشتقة من الفئتين A, B :



objC.A::show();



objC,B:: show();

التسميات: