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

قاعدة العضو الأول

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

عندما تقوم بتضمين struct كـ عضو أول في struct آخر، يحدث شيء قوي: عنوان الذاكرة للـ struct الخارجي مطابق لعنوان الذاكرة لعضوه الأول. هذا مضمون بواسطة معيار C.

تأمل مثالنا السابق:

typedef struct {
    int id;
} Parent;

typedef struct {
    Parent parent;  // العضو الأول
    int grade;
} Child;

عندما تقوم بإنشاء متغير Child، يقع العضو Parent في بداية ذاكرة الـ Child تماماً. هذا يعني أن المؤشر إلى Child يشير إلى نفس العنوان تماماً مثل المؤشر إلى عضو الـ Parent الخاص به.

Child c;
Child* child_ptr = &c;
Parent* parent_ptr = (Parent*)child_ptr;  // تحويل آمن!

كلا المؤشرين يحملان نفس العنوان. هذا يسمح لك بتمرير Child* إلى أي دالة تتوقع Parent*:

void print_id(Parent* p) {
    printf("ID: %d\n", p->id);
}

// في main:
Child c;
c.parent.id = 42;
print_id((Parent*)&c);  // يعمل بشكل مثالي

تعتبر هذه التقنية أساس الوراثة في لغة C. يمكن للدالة المكتوبة للنوع الأساسي (base type) أن تعمل على أي نوع مشتق (derived type)، طالما تم تضمين النوع الأساسي في البداية. تعد عملية التحويل (cast) آمنة لأن تخطيطات الذاكرة (memory layouts) تتطابق تماماً.

challenge icon

التحدي

سهل

دعنا نستكشف قاعدة العضو الأول من خلال بناء تسلسل هرمي بسيط للحيوانات. ستقوم بإنشاء هيكل أساسي Animal وهيكل مشتق Dog، ثم توضح كيف يمكن تحويل مؤشر إلى Dog بأمان إلى مؤشر إلى Animal.

البصيرة الرئيسية التي ستطبقها هي: عندما يكون Animal هو العضو الأول في Dog، يشترك كلا الهيكلين في نفس عنوان ذاكرة البداية. هذا يعني أنه يمكنك تمرير Dog* إلى أي وظيفة تتوقع Animal* عن طريق تحويل المؤشر (casting).

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

  • animal.h: قم بتعريف كلا الهيكلين مع استخدام include guards. يجب أن يحتوي هيكل Animal الخاص بك على حقل واحد: legs (عدد صحيح يمثل عدد الأرجل). يجب أن يدمج هيكل Dog الخاص بك Animal كـ عضو أول ويضيف حقل name (مصفوفة أحرف مكونة من 50 حرفاً). قم أيضاً بالتصريح عن وظيفة print_animal التي تأخذ معامل Animal*.
  • animal.c: قم بتنفيذ وظيفة print_animal. تعمل هذه الوظيفة مع النوع الأساسي — فهي تعرف فقط عن Animal وتطبع عدد الأرجل التي يمتلكها الحيوان.
  • main.c: قم بإنشاء متغير Dog واملأ حقوله (كل من أرجل الحيوان المدمج واسم الكلب). ثم وضح قاعدة العضو الأول عن طريق تحويل Dog* الخاص بك إلى Animal* وتمريره إلى print_animal. قم أيضاً بطباعة اسم الكلب بشكل منفصل لإظهار الصورة الكاملة.

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

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

Dog: Buddy
Legs: 4

حيث Buddy هو اسم الكلب و 4 هو عدد الأرجل. اطبع اسم الكلب أولاً من main.c، ثم استدعِ print_animal مع المؤشر المحول لعرض الأرجل.

يوضح هذا كيف يمكن لوظيفة مكتوبة للنوع الأساسي (Animal) أن تعمل بسلاسة مع نوع مشتق (Dog) من خلال تحويل المؤشر — وهو أساس الوراثة في لغة C.

ورقة مرجعية

عندما يتم تضمين هيكل (struct) كـ عضو أول في هيكل آخر، يشترك كلا الهيكلين في نفس عنوان الذاكرة البدائي. هذا مضمون بواسطة معيار C.

typedef struct {
    int id;
} Parent;

typedef struct {
    Parent parent;  // العضو الأول
    int grade;
} Child;

يمكن تحويل مؤشر (pointer) للهيكل الخارجي بأمان إلى مؤشر لعضوه الأول:

Child c;
Child* child_ptr = &c;
Parent* parent_ptr = (Parent*)child_ptr;  // تحويل آمن - نفس العنوان

يسمح هذا بتمرير مؤشر من نوع مشتق إلى دوال تتوقع النوع الأساسي:

void print_id(Parent* p) {
    printf("ID: %d\n", p->id);
}

Child c;
c.parent.id = 42;
print_id((Parent*)&c);  // يعمل لأن تخطيطات الذاكرة متوافقة

هذه التقنية هي أساس الوراثة في لغة C، مما يُمكّن الدوال المكتوبة للأنواع الأساسية من العمل على الأنواع المشتقة.

جرّب بنفسك

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

int main() {
    // قراءة المدخلات
    char name[50];
    int legs;
    scanf("%s", name);
    scanf("%d", &legs);
    
    // TODO: إنشاء متغير من نوع Dog
    
    // TODO: تعيين اسم الكلب باستخدام strcpy
    
    // TODO: تعيين عدد الأرجل (الوصول من خلال Animal المضمن)
    
    // TODO: طباعة اسم الكلب بالتنسيق: "Dog: <name>"
    
    // TODO: تحويل Dog* إلى Animal* واستدعاء print_animal
    // هذا يوضح قاعدة العضو الأول!
    
    return 0;
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming