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

الوصول إلى أعضاء الأب

جزء من قسم Object Oriented Programming في رحلة C على Coddy — الدرس 30 من 61.

الآن بعد أن فهمنا تضمين الهياكل (struct embedding) وقاعدة العضو الأول (first member rule)، دعونا نركز على الجانب العملي: كيفية قراءة وتعديل بيانات الأب المضمنة من داخل دالة.

عندما تستقبل دالة هيكل Child (أو مؤشرًا إليه)، فإن الوصول إلى أعضاء الأب يتطلب التنقل عبر الهيكل المضمن. تعتمد الصيغة البرمجية على ما إذا كنت تتعامل مع قيمة أو مؤشر.

typedef struct {
    int id;
    int score;
} Parent;

typedef struct {
    Parent parent;
    char grade;
} Child;

باستخدام مؤشر (pointer) إلى Child، استخدم عامل السهم (arrow operator) للوصول إلى parent، ثم النقطة للوصول إلى أعضائه:

void update_score(Child* c, int new_score) {
    c->parent.score = new_score;  // سهم ثم نقطة
}

void print_info(Child* c) {
    printf("ID: %d, Score: %d\n", c->parent.id, c->parent.score);
}

مع قيمة (تُمرر بالنسخ)، استخدم النقاط في كل مكان:

void show_id(Child c) {
    printf("ID: %d\n", c.parent.id);  // نقطة ثم نقطة
}

نمط الوصول المتسلسل هذا — child->parent.member أو child.parent.member — هو الطريقة التي تتفاعل بها مع البيانات الموروثة في نموذج التركيب (composition model) الخاص بلغة C. إنه أكثر إسهاباً قليلاً من الوراثة الحقيقية، لكنه صريح وواضح بشأن العلاقة بين الأنواع.

challenge icon

التحدي

سهل

لنقم ببناء نظام لدرجات الطلاب يوضح كيفية الوصول إلى البيانات وتعديلها داخل هيكل (struct) متداخل. ستقوم بإنشاء تسلسل هرمي حيث يحتوي Student على Person متداخل، ثم تكتب دوالاً تتعامل مع بيانات الأب من خلال الابن.

ستقوم بتنظيم الكود الخاص بك عبر ثلاثة ملفات:

  • student.h: قم بتعريف التسلسل الهرمي للهياكل (structs) مع استخدام حراس التضمين (include guards). أنشئ هيكل Person يحتوي على name (مصفوفة أحرف مكونة من 50 حرفاً) و age (عدد صحيح). ثم قم بتعريف هيكل Student يدمج Person كعضو أول فيه ويضيف حقل grade (عدد صحيح يمثل درجتهم). قم بالتصريح عن دالتين: set_person_age التي تأخذ Student* وقيمة عمر جديدة، و print_student التي تأخذ Student* وتعرض جميع المعلومات.
  • student.c: قم بتنفيذ كلتا الدالتين. يجب أن تقوم دالة set_person_age بتعديل العمر داخل هيكل Person المتداخل — وهنا ستتدرب على بناء جملة السهم ثم النقطة (s->person.age). يجب أن تصل دالة print_student إلى جميع الحقول وتعرضها من كل من الشخص المتداخل والطالب نفسه.
  • main.c: قم بإنشاء متغير من نوع Student وقم بتهيئة جميع حقوله. ثم استخدم set_person_age لتحديث عمر الشخص المتداخل، واستدعِ print_student لعرض النتيجة.

ستتلقى أربعة مدخلات: اسم الطالب (سلسلة نصية)، وعمره الأولي (عدد صحيح)، ودرجته (عدد صحيح)، وعمره الجديد (عدد صحيح لتحديثه عبر دالتك).

في ملفك الرئيسي، قم بإنشاء الطالب بالقيم الأولية، ثم استدعِ set_person_age لتغيير العمر إلى القيمة الجديدة، وأخيراً استدعِ print_student لعرض المعلومات المحدثة.

يجب أن يبدو مخرجك كالتالي:

Name: Emma
Age: 21
Grade: 85

حيث Emma هو الاسم، و 21 هو العمر المحدث (وليس العمر الأولي)، و 85 هي الدرجة. التعلم الأساسي هنا هو التنقل عبر الهيكل المتداخل لقراءة وكتابة أعضاء الأب.

ورقة مرجعية

للوصول إلى أعضاء الـ struct الأب المضمنة من دالة، استخدم صيغة الوصول المتسلسل التي تعتمد على ما إذا كنت تتعامل مع مؤشر (pointer) أو قيمة (value).

مع وجود مؤشر إلى الـ struct الابن، استخدم عامل السهم (arrow operator) للوصول إلى الأب المضمن، ثم تدوين النقطة (dot notation) للوصول إلى أعضائه:

void update_score(Child* c, int new_score) {
    c->parent.score = new_score;  // سهم ثم نقطة
}

void print_info(Child* c) {
    printf("ID: %d, Score: %d\n", c->parent.id, c->parent.score);
}

مع وجود قيمة (يتم تمريرها بالنسخ)، استخدم تدوين النقطة في جميع المراحل:

void show_id(Child c) {
    printf("ID: %d\n", c.parent.id);  // نقطة ثم نقطة
}

هذا النمط — child->parent.member أو child.parent.member — يوفر وصولاً صريحاً إلى البيانات الموروثة في نموذج التركيب (composition model) الخاص بلغة C.

جرّب بنفسك

#include <stdio.h>
#include <string.h>
#include "student.h"

int main() {
    char name[50];
    int initial_age, grade, new_age;
    
    // قراءة المدخلات
    fgets(name, 50, stdin);
    name[strcspn(name, "\n")] = '\0';  // إزالة سطر جديد
    scanf("%d", &initial_age);
    scanf("%d", &grade);
    scanf("%d", &new_age);
    
    // TODO: إنشاء متغير من نوع Student
    
    // TODO: تهيئة جميع حقول الطالب
    // - نسخ الاسم إلى اسم الشخص المضمن باستخدام strcpy
    // - تعيين عمر الشخص المضمن إلى initial_age
    // - تعيين درجة الطالب
    
    // TODO: استدعاء set_person_age لتحديث العمر إلى new_age
    
    // TODO: استدعاء print_student لعرض النتيجة
    
    return 0;
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming