AudaNix

8.5. دالة بناء الفئة Constructors

3 ردود في هذا الموضوع

دالة بناء الفئة Constructors

دالة بناء الفئة Constructors

دالة بناء الفئة هي نوع أستثنائي من دوال أعضاء الفئة يتم تشغيلها عند انشاء نسخة كائن جديد(متغيرجديد) من الفئة. وعادة تستخدم دالة البناء فى تحميل المتغيرات الاعضاء بالقيمة الابتدائية المناسبة من داخل الفئة. او السماح للمستخدم بكل بسهولة بتحميل تلك المتغيرات عند الحاجة بالقيمة المطلوبة.

على عكس الدوال العادية فأن دالة بناء الفئة لها قواعد محددة فى تسميتها:

  1. دالة البناء تكون دائما لها نفس اسم الفئة التى تحتويها(وبنفس حالة الاحرف بالضبط).
  2. دالة البناء لا ترجع أى قيمة ولا حتى قيمة void اى ان لا توجد بها الكلمة الحاكمة return.

دالة البناء التى ليس لها وسائط (او حتى وسائط اختيارية) تسمي دالة البناء الافتراضية a default constructor.

التالى مثال لفئة تستخدم دالة البناء الافتراضية:

class Fraction
{
private:
int m_nNumerator;
int m_nDenominator;

public:
Fraction() // دالة البناء الافتراضية
{
m_nNumerator = 0;
m_nDenominator = 1;
}

int GetNumerator() { return m_nNumerator; }
int GetDenominator() { return m_nDenominator; }
double GetFraction() { return static_cast<double>(m_nNumerator) / m_nDenominator; }
};

هذة الفئة مصممة لتحمل قيمة كسر اعتيادي فى صورة بسط ومقام (numerator & denominator). لقد قمنا بتعريف دالة بناء تسمى Fraction (نفس اسم الفئة). عندما نقوم بأنشاء نسخة(تسمي كائن) من الفئة Fraction فأن يتم استدعاء دالة البناء الافتراضية بمجرد حجز الذاكرة ويتم تحميل الكائن الجديد(النسخة) بالقيم الابتدائية ، والكود التالي مثال على ذلك:

// استدعاء دالة البناء الافتراضية [ltr]Fraction()[/ltr]
Fraction cDefault;
std::cout << cDefault.GetNumerator() << "/" << cDefault.GetDenominator() << std::endl;

ومخرجات الكود:

0/1

لاحظ ان البسط والمقام تم تحميلهما بالقيم الابتدائية بواسطة دالة البناء الافتراضية للفئة! طبعا هذة ميزة جميلة ان تحتوي كل فئة على دالة بناء افتراضية. بدون دالة البناء الافتراضية فأن البسط والمقام سوف يكون لهما قيم عشوائية(garbage) لحين تعيين قيم محددة جديدة لهما.

أضافة الوسائط الى دالة البناء الافتراضية Constructors with parameters

تظل دالة البناء الافتراضية شئ ممتاز للتأكد من ان لفئة يتم تحميلها بالقيم الابتدائة المحددة. ولحسن الحظ فأن دالة البناء الافتراضية يمكن أعلانها بوسائط . التالى مثال على دالة بناء افتراضية تأخذ وسطتين التى تستخدم لتحميل البسط والمقام بالقيم الابتدائية:

#include <cassert>
class Fraction
{
private:
int m_nNumerator;
int m_nDenominator;

public:
Fraction() // دالة البناء الافتراضية
{
m_nNumerator = 0;
m_nDenominator = 1;
}

// دالة البناء الافتراضية تأخذ وسائط
Fraction(int nNumerator, int nDenominator=1)
{
assert(nDenominator != 0);
m_nNumerator = nNumerator;
m_nDenominator = nDenominator;
}

int GetNumerator() { return m_nNumerator; }
int GetDenominator() { return m_nDenominator; }
double GetFraction() { return static_cast<double>(m_nNumerator) / m_nDenominator; }
};

لاحظ ان لدينا عدد اثنين دالة بناء للفئة فى نفس الوقت: دالة البناء الافتراضية التى سوف يتم استدعائها فى الحالة الافتراضية. دالة البناء الثانية تأخذ عدد اثين من الوسائط . فأن دالتى البناء يعملان بنفس الاسم فى نفس الفئة بدون مشاكل لان سي++ تدعم التحميل الزائد على الدوال function overloading. فى الحقيقة يمكنك تعريف اي عدد من البواني كما تريد طالما ان لكل واحد منهم توقيعة الفريد(عدد ونوع الوسائط).

حسنا، كيف نستخدم دالة البناء التى تأخذ وسائط؟ بسيطة:

// استدعاء دالة البناء Fraction(int, int)
Fraction cFiveThirds(5, 3);

الكود السابق سوف يقوم بتحميل cFiveThirds بقيمة الكسر الاعتيادي 5/3 !

ﻻحظ اننا قمنا بأضافة قيم ابتدائية للوسيطة الثانية وهى (int nDenominator=1) في دالة البناء الثانية ولذلك فأن الكود التالي صحيح ايضاً :

Fraction Six(6); // استدعاء الباني Fraction(int, int)

طبعا القية 6 تخص الوسيطة اﻻولى والقيمة الابتدائية تخص الوسيطة الثانية وعندما ﻻ نستخدم الوسيطة الثانية فأن دالة بناء فئة تعين لها القيمة الابتدائية كما هو محدد بالكود (int nDenominator=1) .

لعلك استنتجت ان دالة البناء اﻻفتراضية (اﻻولي) ليس لها فائدة ، يمكننا تبسيط كود الفئة كما بالشكل التالي:

#include <cassert>
class Fraction
{
private:
int m_nNumerator;
int m_nDenominator;

public:
// لاحظ انها اصبحت دالة البناء اﻻفتراضية
Fraction(int nNumerator=0, int nDenominator=1)
{
assert(nDenominator != 0);
m_nNumerator = nNumerator;
m_nDenominator = nDenominator;
}

int GetNumerator() { return m_nNumerator; }
int GetDenominator() { return m_nDenominator; }
double GetFraction() { return static_cast<double>(m_nNumerator) / m_nDenominator; }
};

لقد تم تعريف دالة البناء بطريقة تسمح له بالقيام بوظفية دالة البناء الافتراضية باﻻضافة الى وظيفتا:

Fraction cDefault; // سوف يستدعى Fraction(0, 1)
Fraction cSix(6); // سوف يستدعى Fraction(6, 1)
Fraction cFiveThirds(5,3); // سوف يستدعى Fraction(5,3)

فئات بدون دول بناء أفتراضية Classes without default constructors

ماذا يحدث لو لم نعلن عن دالة البناء الافتراضية للفئة ثم قمنا بعمل نسخة(متغير جديد) من الفئة؟ الذي يحدث ان سي++ سوف تحجز مساحة ذاكرة لنسخة الفئة ولكن لن تقوم بتحميل القيم الابتدائية للمتغيرات اﻻعضاء بأي قيم(يشبة تماما عندما تقوم باﻻعلان عن المتغير من نوع int او double الخ .. ولكن ﻻ تقوم بتحميلة بقيم) مثال:

class Date
{
private:
int m_nMonth;
int m_nDay;
int m_nYear;
};

int main()
{
Date cDate;
// اﻵن المتغيرات اﻻعضاء بــ cDate تحتوي على بيانات عشوائية(garbage).
// نحن ﻻنعرف اي تاريخ نحصل علية ممكن يكون يوم 1000 شهر 5000 سنة -10 !!!!
return 0;
}

فى المثال اعلاة، وبسبب اعلاننا عن كائن Date ، ولكن ﻻيوجد دالة بناء افتراضية فأن m_nMonth و m_nDay و m_nYear لن يتم تحميلها بالقيم الابتدائية نهائيا وسوف يكون بها قيم عشوائيه ، وهذا ما جعل فكرة دالة البناء الافتراضية جيدة ويجب المحافظة عليها فى اكواد:

class Date
{
private:
int m_nMonth;
int m_nDay;
int m_nYear;

public:
Date(int nMonth=1, int nDay=1, int nYear=1970)
{
m_nMonth = nMonth;
m_nDay = nDay;
m_nYear = nYear;
}
};

int main()
{
// ان cDate سوف يتم تحميلها بالقيمة الابتدائية 1/1/1970
Date cDate;
// ان cToday سوف يتم تحميله بالقيمة الابتدائية 9/5/2012
Date cToday(9, 5, 2007);

return 0;
}

تم تعديل بواسطه محمد عودة
2

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

مجهود طيب محمد عودة

لماذا لم يذكروا copy constructor وكذلك The explicit keyword ؟

على كل اسجل متابعتى للدورة وفى انتظار باقى الدروس

تحياتى

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

مجهود طيب محمد عودة

لماذا لم يذكروا copy constructor وكذلك The explicit keyword ؟

على كل اسجل متابعتى للدورة وفى انتظار باقى الدروس

تحياتى

أشكرك على متابعتك وجهدك الحثيث ، سيتم مناقشة موضوع copy constructor فى الدرس 11 فى الفصل التاسع ان شاء الله

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .