الوصول إلى أعضاء الأب
جزء من قسم البرمجة كائنية التوجه في رحلة C على Coddy. الدرس 30 من 61.
الآن بعد أن فهمنا تضمين البنية وقاعدة العضو first، لنركّز على الجانب العملي: كيفية قراءة بيانات parent المضمّن وتعديلها من داخل دالة.
عندما تستقبل دالة بنية Child (أو مؤشرًا إليها)، يتطلب الوصول إلى أعضاء الوالد التنقل عبر البنية المضمّنة. تعتمد الصياغة على ما إذا كنت تتعامل مع قيمة أم مؤشر.
typedef struct {
int id;
int score;
} Parent;
typedef struct {
Parent parent;
char grade;
} Child;باستخدام مؤشرًا إلى Child، استخدم معامل arrow للوصول إلى parent، ثم dot للوصول إلى أعضائه:
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، هو الطريقة التي تتفاعل بها مع البيانات الموروثة في نموذج التركيب في لغة C. وهو أكثر إسهابًا قليلًا من الوراثة الحقيقية، لكنه واضح وصريح بشأن العلاقة بين الأنواع.
التحدي
سهللنَبْنِ نظامًا لتقييم الطلاب يوضّح كيفية الوصول إلى البيانات وتعديلها داخل بنية embedded. ستنشئ تسلسلاً هرميًا يحتوي فيه Student على Person مضمّنة، ثم تكتب functions تعمل مع بيانات parent من خلال child.
ستنظّم code الخاص بك عبر ثلاثة ملفات:
student.h: Define تسلسل البنى الخاص بك مع include guards. Create بنيةPersonتحتوي علىname(مصفوفة من character تتكوّن من 50 character) وage(عدد integer). ثم Define بنيةStudentالتي تضمّنPersonبوصفها أول member لها، وتضيف الحقلgrade(عدد integer يمثّل درجته). Declare اثنتين من functions:set_person_ageالتي تستقبلStudent*وقيمة age جديدة، وprint_studentالتي تستقبلStudent*وتعرض all information.student.c: Implement كلتا functions. يجب أن تعدّل functionset_person_ageالخاصة بك age داخل بنيةPersonالمضمّنة. هنا ستتدرّب على صياغة arrow-then-dot (s->person.age). يجب أن تصل functionprint_studentالخاصة بك إلى all fields من person المضمّن ومن student نفسه، وأن تعرضها.main.c: Create متغيرًا من نوعStudentوInitialize all حقوله. ثم استخدمset_person_ageلتحديث age الخاص بـ person المضمّن، واستدعِprint_studentلعرض النتيجة.
ستتلقى أربعة inputs: name الخاص بـ student (سلسلة نصية)، وinitial age الخاص به (عدد integer)، وgrade (عدد integer)، وnew age (عدد integer لتحديثه عبر function الخاصة بك).
في main file، Create student باستخدام القيم الأولية، ثم استدعِ set_person_age لتغيير age إلى القيمة الجديدة، وأخيرًا استدعِ print_student لعرض information المحدّثة.
يجب أن تبدو Output الخاصة بك كما يلي:
Name: Emma
Age: 21
Grade: 85حيث إن Emma هو name، و21 هو age المحدّث (وليس initial age)، و85 هو grade. يتمثّل الدرس الأساسي هنا في التنقّل عبر البنية المضمّنة لقراءة وكتابة members الخاصة بـ parent.
جرّب بنفسك
#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: هيّئ جميع حقول الـ student
// - انسخ name إلى اسم الشخص المضمّن باستخدام strcpy
// - عيّن عمر الشخص المضمّن إلى initial_age
// - عيّن grade الخاص بـ student
// TODO: استدعِ set_person_age لتحديث العمر إلى new_age
// TODO: استدعِ print_student لعرض النتيجة
return 0;
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات البرمجة التركيبية
ملفات الترويسةحواجز التضمينملفات المصدرالدوال الساكنةمراجعة: آلة حاسبة تركيبية4التغليف (Encapsulation)
مفهوم الـ Opaque Pointersتعريف الـ Opaque Structsالـ Getters والـ Settersالتحقق من البيانات في الـ Settersملخص: الصندوق السري2الكائنات والأساليب
الـ Structs ككائناتمؤشر 'Self'صحة استخدام Constالمؤشر مقابل القيمةالأساليب المساعدةملخص: Point Manager5مشروع: حساب بنكي بسيط
إعداد المشروعتنفيذ الحساب3دورة حياة الكائن
نمط المنشئ (Constructor Pattern)نمط الهادم (Destructor Pattern)تهيئة الـ Stackالنسخ العميق (Deep Copy)مراجعة: String Wrapper6الوراثة عبر التركيب
تضمين الـ Structقاعدة العضو الأولالوصول إلى أعضاء الأبعملية الـ Upcastingمراجعة: هرمية الأشكال9مشروع: رسّام الأشكال
نظرة عامة على المشروعتنفيذ الدائرةتنفيذ المستطيلاستخدام تعدد الأشكالحاوية الأشكالتدرّب بنفسك: مترجم C عبر الإنترنت