درجات الوصول في C++
المتغير public و المتغير private, في الدروس السابقة قمنا بعمل كلاسات Date و كلاس Persone و كلاس Car و تعرَّفنا على كيفية إضافه الخواص للكلاس.
كي يتم إضافه هذه الخواص لكل كائن من هذا الكلاس و تعرَّفنا على كيفية إضافة دالة.
دالة البناء كونستركتور "Constructor" التي تعمل عند بداية كتابة السطر البرمجي الذي تقوم فيه بإنشاء الكائن من الكلاس.
و تحدَّثنا عن private و public و بهذا الدرس سوف نتحدَث اكثر عن private و public و لِما نحتاجهم و كيف يتم التعامل مع المتغيرات من نوع private.
الشكل العام للبرنامج الذي يحتوي متغيرات private و public
#include <iostream>
using namespace std;
class Time{
private:
/يتم وضع العناصر التي لن يتم الوصول إليها عن طريق الدالة ميين
public:
/يتم وضع العناصر التي يتم الوصول إليها عن طريق الدالة من الدالة ميين
};
int main()
{
//انشاء الكائن التي يصل على محتويات public
return 0;
}
مثال 1
سوف نقوم بكتابة مثال عن الوقت Time لأن الوقت يحتوي على ثلاث عناصر رئيسية و هي الساعة و الدقيقة و الثانية.
#include <iostream>
#include <iomanip>
using namespace std;
class Time{
private:
int hour;
int minute;
int second;
public:
Time(int h, int m, int s)
{
hour = h;
minute = m;
second = s;
}
void print()
{
cout << setfill('0');
cout << setw(2) << hour << ":" << setw(2) << minute << ":" << setw(2) << second << endl;
}
};
int main()
{
Time time1(23,3,1);
time1.print();
return 0;
}
لقد قُمنا بإنشاء كلاس بإسم Time و وضعنا به ثلاث مُتغيرات خاصة من نوع private و ثلاث متغيرات عامة من نوع public.
و في المتغيرات الخاصة عرَّفنا متغير int إسمه hour و متغير آخر إسمه minute و متغير ثالث إسمه second.
و في المتغيرات العامة أنشأنا كونستركتور به ثلاث متغيرات معرَّفة على أنها h و m و s و مررنا لهم قيم تعريفهم.
و أنشانا دالة عبر void إسمها print من أجل إستدعائها للطباعة عن طريق الكائن من داخل main.
و وضعنا أمر الطباعة و التنسيق على الشاشة عبر cout و قُمنا بكتابة setfill وضعناها صفر 0 أي بمكان الفراغات يضَع لنا أصفار.
و بداخل دالة الطباعة كتبنا setw(2) من أجل وضع مسافات فارغة أي لتنسيق نافذة الدوس.
و دخلنا للدالة main و أنشأنا كائن time1 و أسندنا له قيم المتغيرات و من ثم عن طريق الكائن إستدعينا دالة الطباعة print.
و عند تشغيل الكود نحصل على النتيجه.
23:03:01
كما نُلاحظ بأنه طَبَعَ لنا الساعة بشكل مُنَظَم و مرتَّب, و إذا قُمنا بإزالة أمر setfill سوف تكون نتيجته غير مرتَّبة و توجد فراغات كما بالشكل.
23: 3: 1
كما لآحظنا من الصورة السابقة قد ترَك لنا مسافات فارغة بين توقيت الساعة, فماذا سوف نحصل إذا قمنا بإزالة الكلمة setw(2) من البرنامج و قمنا بتشغيله.
23:3:1
لآحظنا هنا أنه تمت إزالة المسافات الفارغة التي كانت في نافذة الإخراج السابقة و من هنا فهمنا لماذا قٌمنا بوضع setw(2) و setfill و اهميتهم في مثالنا هذا.
الآن ماذا لو أردنا أن نغير time1 إلى وقت مختلف.
إتفقنا أنه من العادات البرمجية الجيدة أن نقوم بوضع المتغيرات كـ private.
لكن إذا قمنا بكتابة أسفل الكائن بكتابة time1.hour=3 و حاولنا تغيير hour هنا عند بناء البرنامج سوف يقوم بطباعة خطأ كما بالشكل أدناه.
نٌلاحظ إشارة التحذير الحمراء مقابل السطر 27 أي أنه خطأ, لأنه لا يعلم ما هي hour لأن hour في الأعلى تعرفت كـ private.
و بما أنها private لا يمكن الوصول إليها خارج نطاق الكلاس و في دالة Time الكونستركتور يمكن تغيير hour . لذلك قُمنا بتغييرها من خلال إستدعاء الكونستركتور لكن لا يمكن الوصول إليها مباشرتاً لعدة اسباب و هي:
أن لا تقوم بالوصول إلى قيمة hour لأن قيمتها يمكن أن تكون قيمة حساسة.
و إذا قُمنا بكتابة مثلاً time1.hour=55 بهذه الطريقة ستقوم بتغيير متغير قيمته قد ترفض هذا الرقم فلا يمكن لساعه أن تكون تساوي 55 فهي تضع نوعاً ما من الحدود.
فلا يُمكن لأي احد يقوم بإستعمال هذا الكلاس من الوصول إلى بعض القيم الحساسة التي لا تقبل بعض الأرقام المعينة. فهذا هو السبب الأول أن نقوم بالتحقق من القيمة قبل عمل المساواة.
لذلك يمكن الوصول إلى حل اليسَ لدينا فنكشن من نوع public فلِما لا نقوم بعمل فنكشن بداخل الكلاس يقوم بتغيير الساعة كنوع ما للتحايل على القانون.
و بما أن الدوال يمكن الوصول إليها عن طريق main كدالة print يمكن كتابة دالة ثانية نقوم بالوصول إليها مثلاً دالة setHour.
و مرّرنا لها القيمة 55 بهذه الطريقة يمكن تغيير الساعة إلى 55 بنجاح.
و الدالة التي قمنا بإنشائها تُسمى دالة السيتر Setters أي تقوم بتغيير قيمة موجودة في المتغيرات التي نوعها private الموجودة في الأعلى.
مثال 2
إستخدم الشروط و إجبار المستخدم بأن تكون الساعات من 1 حتى 12 و الدقائق من 0 حتى 60 و كذلك الثواني لكي يكون شكل الساعة مُنَظَم. ربما مستخدم يكتُب الساعة 56 و هذا غير منطقي إطلاقاً.
#include <iostream>
#include <iomanip>
using namespace std;
class Time{
private:
int hour;
int minute;
int second;
public:
Time(int h, int m, int s)
{
hour = h;
minute = m;
second = s;
}
void print()
{
cout << setfill('0');
cout << setw(2) << hour << ":" << setw(2) << minute << ":" << setw(2) << second << endl;
}
void setHour(int h)
{
if(h >= 1 && h <= 12)
hour = h;
}
void setMinute(int m)
{
if(m >= 0 && m <= 60)
minute = m;
}
void setSecond(int s)
{
if(s >= 0 && s <= 60)
second = s;
}
};
int main()
{
Time time1(8,3,1);
time1.setHour(55);
time1.setMinute(20);
time1.setSecond(0);
time1.print();
return 0;
}
لقد قمنا بإنشاء دالة setHour من أجل الساعات h و هي من نوع عدد صحيح int ووضعنا له شرط إذا كانت h التي ترمز للساعات اصغر أو يساوي 1 و إذا كانت اصغر أو يساوي 12.
و عرفنا أن hour التي في المتغير الخاص على انها h لترمز للساعات.
و قمنا بإنشاء دالة setMinute من أجل الدقائق m و هي من نوع عدد صحيح int ووضعنا له شرط. إذا كانت m التي ترمز للدقائق اصغر أو يساوي 0 و إذا كانت اصغر أو يساوي 60 و عرفنا أن minute التي في المتغير الخاص على انها m لترمز للدقائق.
و قمنا بإنشاء دالة setSecond من أجل الدقائق s و هي من نوع عدد صحيح int.
و وضعنا له شرط إذا كانت s التي ترمز للثواني اصغر أو يساوي 0 و إذا كانت اصغر أو يساوي 60.
و عرفنا أن second التي في المتغير الخاص على انها s لترمز للثواني.
بعد ذلك في الدالة main قمنا بإنشاء الكائن time1 و اسندنا القيم له.
بعدها قمنا بتعيين قيمة للساعات غير التي عييناها له سابقاً و هي 55 و قيمة للدقائق 20 و قيمة للثواني 0.
و إستدعينا دالة الطباعة عن طريق الكائن time1 و عند تشغيل هذا البرنامج ستكون نتيجته هي.
08:20:00
كما نلاحظ بأنه لم يتم تغيير الساعات إلى 55 كما قلنا له لأنه مجبر أن تكون الساعات من 1 حتى 12.
أما عن الدقائق فتم تغييرها إلى 20 و الثواني تمت تغييرها إلى 0 كما اسلفنا له هذا في الشروط.
مثال 3
قُم بطباعه الساعات أي قم بطباعة فقط time1.hour و hour هو من نوع private.
#include <iostream>
#include <iomanip>
using namespace std;
class Time{
private:
int hour;
int minute;
int second;
public:
Time(int h, int m, int s)
{
hour = h;
minute = m;
second = s;
}
void print()
{
cout << setfill('0');
cout << setw(2) << hour << ":" << setw(2) << minute << ":" << setw(2) << second << endl;
}
void setHour(int h)
{
if(h >= 1 && h <= 12)
hour = h;
}
void setMinute(int m)
{
if(m >= 0 && m <= 60)
minute = m;
}
void setSecond(int s)
{
if(s >= 0 && s <= 60)
second = s;
}
int getHour()
{
return hour;
}
int getMinute()
{
return minute;
}
int getSecond()
{
return second;
}
};
int main()
{
Time time1(8,3,1);
time1.setHour(55);
time1.setMinute(20);
time1.setSecond(0);
time1.print();
cout << time1.getHour() << endl;
return 0;
}
قمنا بإنشاء دالة جديدة و هي setHour من أجل إستدعاء الساعات و هي من نفس نوع المتغير.
لأنها سوف تُعيد قيمة و قيمة الإرجاع هي hour التي في المتغيرات private.
و أنشأنا دالة ثانية setMinute من أجل إستدعاء الدقائق و هي من نفس نوع المتغير int لأنها سوف تعيد لنا القيمة من private و هي minute.
و أنشأنا دالة ثالثة للثواني setSecond لإستدعاء الثواني و تعيد لنا قيمة second.
و في دالة main قمنا بوضع أمر طباعة على شاشة الإخراج و هي time1.getHour من اجل طباعة الساعة فقط.
و هنا قد وصلنا للساعة التي موجودة في private و طباعته على الشاشة.
و عند التشغيل ستكون كما يلي.
08:20:00
8
ملخص درس المتغيرات private و public في C++
إذاً الـ private هي عادة برمجية جيدة يتم كتابة فيها كل المتغيرات التي في الكلاس.
أما البوبلك public فنقوم بكتابة جميع الدوال التي نحتاج الوصول إليها في main.
فعند كتابة time1 و بعدها نقطة سوف يمكننا من الوصول إلى جميع الدوال و حتى المتغيرات من نوع بوبلك.
كما قُلنا من العادات البرمجية الجيدة أن لا اجعل المستخدم يقوم بالتحكم بالمتغيرات بشكل مباشر, بل إجعل هناك طريقة تحايلية. تقوم بتغيير القيم الموجودة بدل من الوصول إليها مباشرتاً بعد القليل من التحقق من القيم المدخلة.