محددات الوصول في C++
جزء من قسم البرمجة كائنية التوجه في رحلة C++ على Coddy. الدرس 34 من 104.
توفر C++ ثلاثة محددات وصول تتحكم فيمن يمكنه الوصول إلى أعضاء الصنف: public وprotected وprivate. وتشكل هذه المحددات أساس التغليف.
class Account {
public:
std::string ownerName; // يمكن الوصول إليه من أي مكان
protected:
double interestRate; // يمكن الوصول إليه في هذه الفئة والفئات المشتقة
private:
double balance; // يمكن الوصول إليه فقط داخل هذه الفئة
};يمكن الوصول إلى الأعضاء العامة من anywhere - داخل الـ class، ومن derived classes، ومن التعليمات البرمجية الخارجية. الأعضاء الخاصة هي الأكثر تقييدًا، ولا يمكن الوصول إليها إلا داخل الـ class نفسه. يقع المحمي بينهما - فهو يتصرف مثل الخاص بالنسبة إلى العالم الخارجي، لكن يمكن لـ derived classes الوصول إلى هذه الأعضاء.
class Account {
private:
double balance;
public:
Account() : balance(0) {}
void deposit(double amount) {
balance += amount; // OK - داخل الـ class
}
};
int main() {
Account acc;
acc.deposit(100); // OK - deposit هو public
// acc.balance = 500; // ERROR - balance هو private
}افتراضيًا، تكون جميع الأعضاء في الفئة خاصةً إذا لم يتم تحديد أي محدِّد. يشجّعك هذا على اتخاذ قرار صريح بشأن ما ينبغي إتاحته. تتمثل الممارسة العامة في جعل أعضاء البيانات خاصةً وتوفير أساليب عامة للتفاعل معها بأمان.
التحدي
سهللنَبْنِ نظامًا بسيطًا لإدارة الموظفين يوضّح كيفية تحكّم محددات الوصول في تحديد من يمكنه الوصول إلى ماذا. ستنشئ class تكون بعض بياناتها خاصة تمامًا، وبعضها متاحًا للفئات المشتقة المحتملة، وبعضها مفتوحًا للجميع.
ستنشئ ملفين لتنظيم التعليمات البرمجية:
Employee.h: Define فئةEmployeeتستخدم محددات الوصول الثلاثة لحماية البيانات بالشكل المناسب:- Public: اسم الموظف
name(سلسلة نصية). يمكن الوصول إليه من anywhere - Protected:
departmentالموظف (سلسلة نصية): يمكن الوصول إليه داخل الفئة ومن خلال الفئات المشتقة، ولكن ليس من خارجها - Private: راتب الموظف
salary(عدد عشريdouble): لا يمكن الوصول إليه إلا من داخل الفئة نفسها - Constructor يأخذ الاسم وdepartment والراتب لتهيئة جميع members الثلاثة
- دالة method عامة
getSalary()تُرجع قيمة الراتب الخاص - دالة method عامة
getDepartment()تُرجع قيمة department المحمي - دالة method عامة
giveRaise(double amount)تزيد الراتب بالمقدار المحدد (فقط إذا كان amount موجبًا) - دالة method عامة
displayInfo()تطبع information الموظف بالتنسيق:"Name: <name>, Department: <department>, Salary: $<salary>"
- Public: اسم الموظف
main.cpp: وضّح كيفية عمل محددات الوصول من خلال التفاعل مع كائنEmployee. اقرأ اسم الموظف وdepartment والراتب من input (ثلاثة أسطر منفصلة)، ثم:- Create كائن
Employeeباستخدام قيم input - اطبع اسم الموظف مباشرةً من خلال الوصول إلى member العام:
"Direct access - Name: <name>" - اطبع department باستخدام getter:
"Via getter - Department: <department>" - اطبع الراتب باستخدام getter:
"Via getter - Salary: $<salary>" - امنح الموظف زيادة قدرها
5000.0 - اطبع
"After raise:" - استدعِ
displayInfo()لعرض information المحدّثة
- Create كائن
نسّق جميع قيم الراتب باستخدام منزلتين عشريتين بواسطة std::fixed وstd::setprecision(2) من <iomanip>. حوّل input الراتب من سلسلة نصية إلى عدد عشري باستخدام std::stod().
الفكرة الأساسية هنا هي أنه بينما يمكنك الوصول إلى name مباشرةً من main، لا يمكنك الوصول إلى department أو salary مباشرةً. يجب أن تستخدم دوال getter العامة. هذا هو مبدأ التغليف أثناء العمل: تتحكّم الفئة في كيفية الوصول إلى بياناتها وتعديلها.
جرّب بنفسك
#include <iostream>
#include <string>
#include <iomanip>
#include "Employee.h"
using namespace std;
int main() {
// اقرأ المدخلات
string name;
string department;
string salaryStr;
getline(cin, name);
getline(cin, department);
getline(cin, salaryStr);
double salary = stod(salaryStr);
// عيّن الدقة لمخرجات الراتب
cout << fixed << setprecision(2);
// TODO: أنشئ كائن Employee بالقيم المدخلة
// TODO: اطبع اسم الموظف بالوصول إلى العضو العام مباشرة
// Format: "Direct access - Name: <name>"
// TODO: اطبع القسم باستخدام طريقة الـ getter
// Format: "Via getter - Department: <department>"
// TODO: اطبع الراتب باستخدام طريقة الـ getter
// Format: "Via getter - Salary: $<salary>"
// TODO: امنح الموظف زيادة قدرها 5000.0
// TODO: اطبع "After raise:"
// TODO: استدعِ displayInfo() لعرض المعلومات المحدّثة
return 0;
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات الـ OOP
الملفات الخارجيةبناء وتجميع (Compilation) لغة C++ملفات الـ Header وملفات الـ Sourceالـ Namespaces والـ Scopeمقدمة في الـ OOP في C++الـ Classes مقابل الـ Objectsالمؤشر 'this'الـ Methods (الدوال الأعضاء)الـ Attributes (بيانات الأعضاء)أساسيات الـ Ctors والـ Dtorsمراجعة - آلة حاسبة بسيطة4خصائص الـ Class
أعضاء الـ Instance مقابل الـ Staticدوال الـ Getters والـ Settersدوال الأعضاء الثابتة (Const)الكلمة المفتاحية Mutableالدوال والمتغيرات الساكنة (Static)الدوال والفئات الصديقة (Friend)مراجعة - مدير الحساب البنكي7الوراثة
الوراثة الأساسيةمستويات الوصول في الوراثةترتيب استدعاء الـ Ctor والـ Dtorإعادة تعريف الدوال (Method Overriding)الدوال الافتراضية والـ VTableالوراثة المتعددةالوراثة الافتراضيةمراجعة - هيكلية الموظفين10نظرة عامة على STL
نظرة عامة وفلسفة STLحاويات STLالـ Iteratorsخوارزميات STLالـ Functors وتعبيرات Lambdaمراجعة - تكرار الكلمات13أنماط التصميم - الجزء الأول
مقدمة في أنماط التصميمنمط Singletonنمط Factory و Abstract Factoryنمط Builderنمط Observerنمط Strategy2إدارة الذاكرة
ذاكرة Stack مقابل Heapالمؤشرات والمراجعالذاكرة الديناميكية (new/delete)المؤشرات الذكية في C++RAII في C++مراجعة - مدير المصفوفات الديناميكية5التغليف (Encapsulation)
محددات الوصول في C++محددات الوصول بشكل متعمقإخفاء المعلوماتStruct مقابل Classالأصناف المتداخلة والداخليةمراجعة - نظام سجلات الطلاب8تعدد الأشكال (Polymorphism)
تعدد الأشكال: وقت التجميع مقابل وقت التشغيلالتحميل الزائد للدوال (Function Overloading)مراجعة الدوال الافتراضية (Virtual Functions)الدوال الافتراضية البحتة (Pure Virtual Functions)الأصناف المجردة (Abstract Classes)تصميم الواجهات (Interface) في C++التحويل الديناميكي (Dynamic Casting) و RTTIملخص - حاسبة الأشكال11مفاهيم OOP المتقدمة
التركيب مقابل الوراثةالـ Mixins عبر CRTPنمط Pimplمحو النوع (Type Erasure)أصناف Enum والأنواع القويةمعالجة الاستثناءات في OOPتسلسلات الاستثناءات المخصصة14أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط قالب الطريقةنمط الحالةنمط التركيبRAII كنمط3المنشئات والموادم
المنشئ الافتراضيالمنشئ ذو المعاملاتمنشئ النسخمنشئ النقلقوائم تهيئة المنشئالمنشئات المفوضةتعمق في الموادمقاعدة الثلاثة / الخمسة / الصفرمراجعة - فئة String6تحميل العوامل (Operator Overloading)
مقدمة في تحميل العواملتحميل العوامل الحسابيةتحميل عوامل المقارنةعوامل Streamتحميل عامل التعيينتحميل العوامل [] و ()عوامل تحويل النوعمراجعة - Matrix Class9القوالب
قوالب الدوالقوالب الأصنافتخصيص القوالبالقوالب المتغيرةأساسيات SFINAE و Type Traitsمراجعة - الحاويات العامةتدرّب بنفسك: مترجم C++ عبر الإنترنت