بتـــــاريخ : 2/22/2011 9:10:06 PM
الفــــــــئة
  • الحـــــــــــاسب
  • التعليقات المشاهدات التقييمات
    0 1283 0


    تقنية تعدد الوجهيات (الاوجه - الاشكال) polymorphism الدرس الثاني

    الناقل : elmasry | العمر :42 | الكاتب الأصلى : time1 | المصدر : www.arabteam2000-forum.com

    كلمات مفتاحية  :

    بسم الله الرحمن الرحيم
    اقدم اليوم لكم الدرس الثاني بموضوع polymorphism
    ______________________________________________________________________________

    الربط الديناميكي
    dynamic binding

    لو قام برنامج باستدعاء تابع(دالة) ظاهري باستخدام مؤشر من نمط صف اساسي إلى غرض تابع إلى صف مشتق ,فإنه سيقوم باختيار التابع المناسب ديناميكيا ً.
    ونسمي هذه العملية (اي اختيار التابع المناسب اثناء زمن التنفيذ ) بالربط الديناميكي dynamic binding.


    سنعرض مثال نصممه بالاستعانه بتقنية تعدد الاشكال(الاوجه -الوجهيات ) polymorphism هذا المثال يقوم بطلب المستخدم بادخال قيمة ومن ثم ينظر للقيمة اذا كانت اقل من 10 ينشأ غرض A ويعطيه القيمة اما اذا كان خلاف ذلك سيقوم بانشاء غرض B ويعطيه القيمة
    الصف(class -الصنف) A يحتوي على دالة طباعة تقوم بعرض القيمة فقط
    اما الصف B يحتوي على دالة طباعة تقوم بعرض القيمة بعد خصم 5% من القيمة الاصلية.

    #include<iostream>
    using std::cout;
    using std::cin;
    using std::endl;
    #include<new>

    class A
    {
    public:
            A(int=0);
            virtual print();
    protected:
            int x;
    };
    A::A(int a)
    {
    x=a;
    }
    A::print()
    {
                    cout<<"This Class is A and The value :"<<x<<"it is less than 10"<<endl;
    }

    class B:public A
    {
    public:
            B(int=0);
             print();
    private:
            int y;
    };
    B::B(int a)
    {
            y=a;
    }
    B::print()
    {
                    cout<<"This Class is B and The value is:"<<y<<" . it is more than 10 and the value aftar  the discount is 5% ,Now The value is :"<<y-((5*y)/100)<<endl;
    }
    main()
    {

            int value;
            A *p=NULL;
            cout<<"Enter The value";
            cin>>value;
            if(value<10)
                    p=new A(value);
            else
                    p=new B(value);
            p->print();
            return 0;
    }



    _____________________________________________________________________________

    نأتي الان إلى موضوع نظري وهو Switch
    يمكن لنا من خلال تعليمة Switch ان نقوم باستدعاء التوابع من صفوفها على حسب الشرط الذي يتحكم بنوع النمط(الصف-الصنف-الفئة-class) ,وهذه طريقة مجدية , ويمكن ان تكون باستخدام if لكن !
    في الانماط المتقدمة والتي تعتمد على مستويات متعدده في البنى الهرمية سيكلف هذا وقتا كثيرا وربما نواجه اخطاء بارسال رسائل غير موجودة داخل الصف , ايضا ربما ينسى المبرمج ان يقوم بعمليات الفحص المطلوبة بشكل صحيح , وكذلك اي تغيير لأي صف من صفوف البنى الهرمية يعتبر تعديلا على عملية switch من جديد وهذا يكلف وقتا كبيرا ويزيد من احتمالية الاخطاء .

    لذلك اتت تقنية تعدد الاشكال(الاوجه- الوجهيات) polymorphism لتحل هذه المشكلة وتسهل استخدامها داخل البرامج ذات المستويات المتعدده داخل بنية هرمية.
    ملاحظة :مصظلح "رسالة" مرادف لمصطلح "استدعاء تابع" .


    *****************************************************************************
    سنتكلم اليوم عن موضوع من اهم مواضيع polymorphism تعدد الاشكال.
    الصفوف المجردة والصفوف الجسدة و التوابع الظاهرية الصافية (الصوافي) pure virtual function

    التوابع الظاهرية الصافيه (الصوافي) pure virtual function:
    هذه التوابع هي توابع ظاهرية ولكن تتميز بكلمة صافيه فماذا تعني ؟!
    تعني كلمة صافيه انها توابع تتواجد في صفوف خاصة تسمى الصفوف المجردة كنماذج فقط ويتم تعريفها في الصفوف المشتقة.
    والفائدة من هذه التوابع انه في بعض البنى الهرمية نقوم بتعريف صف اساسي ويوجد مثلا دالة طباعة print لا نحتاجها في الصف الاساسي , وانما نحتاجها في الصفوف المشتقة فقط . لذلك نقوم بتعريفها على انها توابع صافيه بإعطائها قيمة pure
    القيمة pure:
    لكي نعطي دالة قيمة pure لنجعلها دالة صافيه , نقوم بماسواتها بالصفر اثناء تعريف النموذج
    مثلا:
    virtual print()=0

    ربما يستبهم الامر على القارء وانا اعلم ذلك لكن يكتفي حاليا في قراءة التعاريف التي ستفهم في مثالنا القادم.

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

    سنعرض لكم الان مثال جيد لشرح التوابع الظاهرية والظاهرية الصافيه والصفوف المجردة والصفوف المشتقة من خلال بنية هرمية مكونه من مستويين .
    (ملاحظة:في حال استبهام التعاريف ارجوا فهم المثال ومحاولة اعادة تجريبه , ثم العودة مرة اخرى للتعاريف ومقارنتها مع استخدامها داخل المثال .
    _____________________________________________________________________________

    #ifndef PROJECT_H
    #define PROJECT_H
    class project
    {
    public:
            virtual char *getname()=0;
            virtual getnum();
            virtual print()=0;
            virtual getSalary();
            virtual retired();

    };
    #endif


    الملف الرأسي لتعريف الصف project

    #include<iostream>
    using namespace std;
    #include"project.h"
    project::getnum()
    {
            return 0;
    }
    project::getSalary()
    {
            return 0;
    }
    project::retired()
    {
            return 0;
    }


    الصف project

    #ifndef STUDENT_H
    #define STUDENT_H

    #include"project.h"
    class student:public project
    {
    public:
            student(char * ="",int=0);
            virtual char *getname();
            virtual getnum();
            virtual print();
           
    protected:
            char *name;
            int number;
           

    };
    #endif


    الملف الرأسي لتعريف الصف student

    #include<iostream>
    using namespace std;
    #include"student.h"
    student::student(char *nam,int num)
    {
            name=nam;
            number=num;
    }

    char *student::getname()
    {
            return name;
    }
    student::getnum()
    {
            return number;
    }
    student::print()
    {
            cout<<"This Class Is Student Class";
    }


    الصف لـstudent

    #ifndef LABOURER_H
    #define LABOURER_H

    #include"student.h"
    class labourer:public student
    {
    public:
            labourer(char * = "",int =0,int=0,int=0);
            virtual char *getname();
            virtual getnum();
            virtual print();
            virtual getSalary();
            virtual retired();
    private:
            int salary;
            int old;
    };
    #endif


    الملف الرأسي لتعريف الصف labourer

    #include<iostream>
    using namespace std;
    #include"labourer.h"
    #include"student.h"
    labourer::labourer(char *nam,int num,int sal,int ore):student(nam,num)
    {
            salary=sal;
            old=ore;
    }

    char *labourer::getname()
    {
            return name;
    }
    labourer::getnum()
    {
            return number;
    }

    labourer::getSalary()
    {
            return salary;
    }
    labourer::retired()
    {
            return old+60;
    }
    labourer::print()
    {
            cout<<"This Class Is Labourer"<<endl;
    }


    الصف labourer


    #include<iostream>
    using namespace std;
    #include"project.h"
    #include"student.h"
    #include"labourer.h"
    void doit(project *pointer)
    {
            cout<<"Name is :"<<pointer->getname()<<endl;
            cout<<"Number is :"<<pointer->getnum()<<endl;
            cout<<"Salary is :"<<pointer->getSalary()<<endl;
            cout<<"Retired :"<<pointer->retired()<<endl;
            pointer->print();
            cout<<endl;
    }
                   
           
    main()
    {
            project *p=NULL;
            student st("Ali",104);
            labourer la("Ahmad",219,1520,1988);
            p=&st;
            doit(p);
            p=&la;
            doit(p);
            return 0;
    }



    ___________________________________________________________________________
    البرنامج

    يقوم البرنامج على ثلاثة صفوف
    الأول هو project
    وهو صف مجرد لا يمكن ان نشتق اغراض منه لذلك كما قلنا هو يمثل ارضية العمل , فيحتوي على الدوال الموجودة في الصفوف الموجودة بالمستويات الوراثية.
    نلاحظ تعريف الدالة print والدالة getname على انهما دالتان ظاهريتان صافيتان وذلك عن طريق اعطائهم قيمة pure
    كما ونلاحظ ظرورة تعريفهم في اول مستويات الوراثة (الصف student )
    اما باقي الدوال فهي دوال ظاهرية فقط ونلاحظ انها معرفة في الصف المجرد , وذلك من اجل ارسال اي رسالة (عن طريق مؤشر على الصف الاساسي المجرد ) في صف مشتق ولم تكن موجودة فيه.
    الصفوف الاخرى
    student & labourer
    هذه صفوف مجسدة يمكن اشتقاق اغراض منها كما هو مبين من البرنامج
    يأخذ الصف student اسم الطالب وكذلك رقمه (اي رقم كمثال فقط )
    يأخذ الصفlabourer اسم الموظف ورقمه وراتبه وسنة ولادته.
    الدوال
    getname تعيد الاسم
    getnum تعيد الرقم
    getSalary تعيد الراتب
    retired تعيد سنة التقاعد وهي سنة الميلاد زائد 60
    دالة print تقوم بطباعة اسم الصف
    في داخل البرنامج (fig)
    يتم اشتقاق مؤشر من الصف الاساسي المجرد project
    ثم اشتقاق اغراض لكلا الصفين student & labourer
    تم اعطاء المؤشر عنوان غرض الصف student وتم اعطاء المؤشر لدالة doit ثم تمت نفس العملية مع الصف labourer
    الدالة doit تقوم بطباعة الاسم والرقم والراتب وسنة التقاعد واسم الصف عن طريق استدعاء الدوال بواسطة المؤشر pointer

    ستكون المخرجات
    Name Is:Ali
    Number Is : 104
    Salary Is:0 R.S
    retired:0
    This Class Is Student Class
    Name Is:Ahmad
    Number Is : 104
    Salary Is:0 R.S
    retired:2048
    This Class Is Labourer

    _________________________________________________________________________
    هكذا اكون قد انهيت الدرس الثاني.
    اتمنى من المولى القدير ان اكون قد وفقت في طرحه
    مع تمنياتي لكم بالتوفيق
    ملاحظة: بالنسبة للمصطلحات قمت بكتابة المصطلح على حسب ماورد بأغلب الكتب وايضا كتبة اسمه باللغة الانجليزية .
    :)

     

    كلمات مفتاحية  :

    تعليقات الزوار ()