التوارث المتعدد في ++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();
تعليقات
إرسال تعليق