Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

محددات الوصول بشكل متعمق

جزء من قسم البرمجة كائنية التوجه في رحلة C++ على Coddy. الدرس 35 من 104.

الآن بعد أن فهمت محددات access الثلاثة، لِنستكشف كيفية تصرّفها عندما يكون لديك عدة كائنات من class نفسها. من المفاهيم الخاطئة الشائعة أن private تعني «هذا الكائن فقط» — لكنها تعني في الواقع «هذه class فقط».

يمكن للكائنات من الفئة نفسها الوصول إلى الأعضاء الخاصة لبعضها البعض:

class Person {
    std::string secret;
    
public:
    Person(std::string s) : secret(s) {}
    
    void readSecret(const Person& other) {
        // الوصول إلى عضو خاص لكائن آخر - مسموح!
        std::cout << other.secret;
    }
};

يعمل هذا لأن التحكم في access يتم فرضه على مستوى الفئة، وليس على مستوى الكائن. تُعدّ الطريقة readSecret جزءًا من الفئة Person، لذا يمكنها الوصول إلى الأعضاء الخاصين لأي كائن من نوع Person. يتيح هذا التصميم لعمليات مثل مُنشئات النسخ وعوامل المقارنة العمل مع الحالة الداخلية للكائنات الأخرى.

يمكنك أيضًا التبديل بين محددات الوصول عدة مرات داخل الفئة:

class Mixed {
public:
    void publicMethod1();
    
private:
    int privateData;
    
public:
    void publicMethod2();    // العودة إلى public
    
private:
    void privateHelper();    // private مرة أخرى
};

مع أن هذا صالح في C++، فمن الأفضل عمومًا تجميع الأعضاء حسب مستوى access لتحسين سهولة القراءة. توصي معظم أدلة الأسلوب بإدراج الأعضاء public أولًا (لأنهم يشكّلون واجهة class)، يليهم protected، ثم private.

challenge icon

التحدي

سهل

لنبنِ نظامًا لمقارنة المحافظ يوضّح كيف يمكن للكائنات من الفئة نفسها الوصول إلى الأعضاء الخاصة لبعضها بعضًا. هذه فكرة أساسية حول التحكم في الوصول في C++: إذ يُفرَض على مستوى الفئة، وليس على مستوى الكائن.

ستنشئ ملفين لتنظيم التعليمات البرمجية:

  • Wallet.h: عرّف فئة Wallet تخزّن بيانات مالية خاصة، لكنها تسمح بإجراء المقارنات بين المحافظ. يجب أن تحتوي فئتك على:
    • أعضاء خاصة: ownerName (سلسلة نصية) وbalance (عدد عشري مزدوج)
    • منشئ يستقبل اسم المالك والرصيد الأولي
    • دالة وصول عامة getOwnerName() تُعيد اسم المالك
    • دالة hasMoreThan(const Wallet& other) تقارن رصيد هذه المحفظة بالرصيد الخاص لمحفظة أخرى، وتُعيد true إذا كانت هذه المحفظة تحتوي على أموال أكثر
    • دالة combinedBalance(const Wallet& other) تُعيد مجموع الرصيدين الخاصين للمحفظتين
    • دالة transferTo(Wallet& other, double amount) تنقل الأموال من هذه المحفظة إلى أخرى. ويجب أن تعدّل مباشرةً الرصيدين الخاصين للمحفظتين (فقط إذا كان amount موجبًا ولا يتجاوز رصيد هذه المحفظة)
  • main.cpp: وضّح الوصول إلى الأعضاء الخاصة عبر الكائنات. اقرأ اسمي مالكين ورصيدين من الإدخال (أربعة أسطر: name1 وbalance1 وname2 وbalance2)، ثم:
    • أنشئ كائنين من Wallet باستخدام قيم الإدخال
    • اطبع "Combined wealth: $<amount>" باستخدام combinedBalance()
    • قارن بين المحفظتين واطبع "<name> has more money" للمالك الذي لديه الرصيد الأعلى (استخدم hasMoreThan() لتحديد ذلك)
    • انقل 100.0 من المحفظة الأولى إلى الثانية باستخدام transferTo()
    • اطبع "After transfer:"
    • اطبع "Combined wealth: $<amount>" مرة أخرى (يجب ألا يتغير)
    • قارن مرة أخرى واطبع "<name> has more money" (قد تكون النتيجة قد تغيّرت)

المفهوم الأساسي هنا هو أن دوالًا مثل hasMoreThan() وtransferTo() يمكنها الوصول مباشرةً إلى عضو balance الخاص بكائن Wallet آخر: فلا حاجة إلى دوال وصول. ويعمل ذلك لأن التحكم في الوصول في C++ قائم على مستوى الفئة: إذ يمكن لأي تعليمات برمجية داخل فئة Wallet الوصول إلى الأعضاء الخاصة في أي كائن من Wallet.

نسّق جميع القيم المالية باستخدام منزلتين عشريتين عبر std::fixed وstd::setprecision(2) من <iomanip>. حوّل مدخلات الرصيد باستخدام std::stod().

جرّب بنفسك

#include <iostream>
#include <string>
#include <iomanip>
#include "Wallet.h"

using namespace std;

int main() {
    // اقرأ المدخلات: name1, balance1, name2, balance2
    string name1, name2;
    string balanceStr1, balanceStr2;
    
    getline(cin, name1);
    getline(cin, balanceStr1);
    getline(cin, name2);
    getline(cin, balanceStr2);
    
    double balance1 = stod(balanceStr1);
    double balance2 = stod(balanceStr2);
    
    // اضبط تنسيق الإخراج للقيم النقدية
    cout << fixed << setprecision(2);
    
    // TODO: أنشئ كائنين من Wallet بالقيم المدخلة
    
    // TODO: Print combined wealth using combinedBalance()
    // Format: "Combined wealth: $<amount>"
    
    // TODO: Compare wallets using hasMoreThan() and print who has more money
    // Format: "<name> has more money"
    
    // TODO: انقل 100.0 من المحفظة الأولى إلى الثانية باستخدام transferTo()
    
    // TODO: Print "After transfer:"
    
    // TODO: Print combined wealth again
    
    // TODO: Compare again and print who has more money
    
    return 0;
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم C++ عبر الإنترنت