كيف تعمل الأصناف في ++C؟ دليل عملي لفهم Classes وObjects

دقائق القراءة: 8
شرح كيفية عمل الأصناف في لغة سي بلس بلس مع الكائنات والدوال العضوية

مقدمة: لماذا تُعد الأصناف أساس البرمجة الكائنية في C++؟

تدعم لغة C++ مفهوم البرمجة كائنية التوجّه، وتُعد classes وobjects الركيزة الأساسية لهذا الأسلوب. وعند بداية تعلّم اللغة، يواجه كثير من المطورين سؤالاً مهماً: ما هو class بالضبط، ولماذا نحتاج إليه إذا كانت اللغة توفر أنواعاً جاهزة مثل int وbool وfloat؟

الإجابة المختصرة هي أن الأصناف تمنحك القدرة على بناء أنواع بيانات مخصّصة تعبّر عن كيانات واقعية أو منطقية داخل البرنامج، مثل كتاب أو سيارة أو مستخدم أو طلب شراء. وبدلاً من الاعتماد فقط على الأنواع المدمجة، يمكنك تصميم نوع يناسب احتياجك الفعلي بدقة أكبر.

الأنواع المدمجة في C++ وكيف مهدت لفكرة الأصناف

توفر C++ مجموعة من الأنواع الجاهزة مثل bool وint وfloat وغيرها. لكل نوع خصائصه، مثل حجم الذاكرة التي يشغلها وطريقة التعامل معه عبر المعاملات المختلفة.

على سبيل المثال، يقوم المعامل + بجمع القيم عندما يُستخدم مع أعداد من نوع int أو float أو double:

int x = 5;
int y = 6;
int z = x + y; // z == 11

لكن إذا استُخدم المعامل نفسه مع سلاسل نصية من نوع string، فإنه لا يجمعها حسابياً، بل يربطها معاً:

string s1 = "abhilekh";
string s2 = "gautam";
string s3 = s1 + s2; // s3 will be abhilekhgautam

في المثال الأول، تمثل المتغيرات x وy وz كائنات من النوع int. وفي المثال الثاني، تمثل s1 وs2 وs3 كائنات من النوع string.

من المهم هنا فهم أن object هو أي كيان يشغل مساحة في الذاكرة. لكن الأنواع المدمجة وحدها لا تكفي دائماً لتمثيل مفاهيم الحياة الواقعية داخل البرنامج، وهنا تظهر الحاجة إلى classes.

ما هو class في C++؟

الصنف أو class هو نوع بيانات يعرّفه المستخدم بنفسه. بمعنى آخر، يمكنك إنشاء نوع جديد كما لو كنت تنشئ نوعاً شبيهاً بـ int أو char، لكن بخصائص وسلوكيات من تصميمك.

إذا أردت مثلاً تمثيل كتاب داخل البرنامج، فمن المنطقي أن يحتوي هذا الكيان على بيانات مثل اسم المؤلف والعنوان وعدد الصفحات ورقم الطبعة. يمكن تمثيل ذلك باستخدام صنف خاص:

class Book {
    string author_name, title;
    int no_of_pages, edition_no;
    //...
};

في هذا المثال أنشأنا صنفاً باسم Book. ويضم هذا الصنف مجموعة من الأعضاء members التي تصف خصائص الكتاب.

ما الفرق بين تعريف الصنف وإنشاء كائن منه؟

إنشاء الصنف وحده لا يكفي، لأنه يحدد القالب فقط. لكي يصبح لهذا القالب وجود فعلي في الذاكرة، يجب إنشاء كائن object منه:

int x;   // x is an object of type int
Book y;  // y is an object of type Book

الفرق هنا أن x كائن من نوع مدمج توفره اللغة، بينما y كائن من نوع مخصص أنشأته أنت، وهو Book.

الدوال العضوية في C++ وكيف تعمل

الدوال التي تُعرَّف داخل الصنف تُسمى member functions. وهي تمثل السلوك المرتبط بالكائنات التابعة لذلك الصنف. فإذا كانت البيانات تصف حالة الكائن، فإن الدوال العضوية تصف ما يمكن لهذا الكائن أن يفعله.

لنطوّر الصنف Book بإضافة دالة لتحديث رقم الطبعة:

class Book {
    //..
public:
    void update_edition(int edition);
    //..
};

أصبحت الدالة update_edition() دالة عضوية ضمن الصنف Book.

تعريف الدالة داخل الصنف

يمكن تعريف الدالة مباشرة داخل جسم الصنف:

class Book {
    //..
public:
    void update_edition(int edition) {
        edition_no = edition;
    }
};

تعريف الدالة خارج الصنف

كما يمكن التصريح بها داخل الصنف، ثم تعريفها لاحقاً خارجه باستخدام العامل :: المعروف باسم scope resolution operator:

void Book::update_edition(int edition) {
    // Define your function here
    //..
}

استدعاء الدوال العضوية

بعد إنشاء كائن من الصنف، يمكن استدعاء الدالة من خلاله:

Book y;
y.update_edition(5);

ولا يمكن استدعاء هذه الدالة من كائن لا ينتمي إلى الصنف Book، وإلا سيؤدي ذلك إلى خطأ نحوي أو منطقي حسب السياق.

المؤشر this داخل الدوال غير الساكنة

الدالة العضوية غير الساكنة non-static member function تعرف دائماً الكائن الذي تم استدعاؤها من خلاله. ويمكن الوصول إلى هذا الكائن عبر المؤشر this:

void Book::update_edition(int edition) {
    this->edition_no = edition;
}

استخدام this مفيد عندما تريد توضيح أنك تشير إلى عضو داخل الكائن الحالي، خصوصاً عند تشابه أسماء المعاملات مع أسماء الخصائص.

أنواع الدوال العضوية في C++

لا تقتصر الدوال العضوية على شكل واحد، بل توجد عدة أنواع مهمة يجب فهمها جيداً عند تصميم الأصناف.

الدوال العضوية الثابتة من حيث الحالة const member functions

إذا كانت الدالة لا يجب أن تعدّل حالة الكائن، فيمكن تعريفها كدالة const:

class Book {
    //..
public:
    int display_edition() const {
        return edition_no;
    }
    //..
};

إضافة الكلمة المفتاحية const تعني أن هذه الدالة لا تغيّر بيانات الكائن. وإذا حاولت تعديل عضو داخلي من داخلها، فسيظهر خطأ:

int Book::book_edition() const {
    edition_no = edition_no + 1; // error: cannot change value in constant function
}

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

الدوال العضوية الساكنة static member functions

عندما تحتاج إلى دالة ترتبط بالصنف نفسه لا بكل كائن على حدة، يمكنك تعريفها كدالة static. هذه الدالة تكون جزءاً من الصنف، لكنها لا تنتمي إلى كائن محدد منه:

class Book {
    //..
public:
    static void my_static_func();
};

تعريفها خارج الصنف يكون كالتالي:

void Book::my_static_func() {
    // define here.
}

ومن خصائص هذا النوع:

  • يمكن استدعاؤه باسم الصنف دون الحاجة إلى إنشاء كائن.
  • لا يملك وصولاً إلى المؤشر this.
  • يناسب العمليات العامة المرتبطة بالصنف لا بحالة كائن بعينه.

دوال الصداقة friend functions والأصناف الصديقة

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

مثال على جعل دالة عضو من صنف آخر صديقة:

class Book {
    //..
public:
    void check();
    void display();
    //..
};

class E_book {
    //..
public:
    //..
    friend void Book::check();
};

أما إذا أردت جعل جميع دوال صنف معين صديقة لصنف آخر، فيمكنك استخدام:

class E_book {
    //...
public:
    //..
    friend class Book;
};

بهذا تصبح جميع دوال الصنف Book قادرة على الوصول إلى الأعضاء التي يسمح بها إعلان الصداقة داخل E_book.

محددات الوصول Access Specifiers في الأصناف

إذا كانت لديك خلفية بلغة C، فربما سبق أن استخدمت الكلمة المفتاحية struct لتعريف نوع مخصص:

struct Book {
    char author_name[20];
    char title[20];
    int no_of_page, edition_no;
};

Book b1; // b1 is an object of type Book

الهيكل struct في C++ هو أيضاً نوع يعرّفه المستخدم. ويمكن اعتباره شبيهاً بـ class إلى حد كبير، لكن الفرق الأساسي أن أعضاء struct تكون public افتراضياً، بينما أعضاء class تكون private افتراضياً إذا لم تحدد غير ذلك.

الفرق بين private وpublic

  • private: الأعضاء بعد هذا المحدد لا يمكن الوصول إليها إلا من داخل الدوال العضوية للصنف نفسه.
  • public: الأعضاء بعد هذا المحدد يمكن الوصول إليها من أي مكان يسمح به نطاق البرنامج.

تُستخدم محددات الوصول لتحقيق مفاهيم أساسية في التصميم البرمجي مثل:

  • إخفاء البيانات data hiding
  • التجريد data abstraction
  • التغليف data encapsulation

وهذه المفاهيم ليست مجرد تفاصيل نظرية، بل هي أساس بناء كود أكثر أماناً وتنظيماً وسهولة في التطوير لاحقاً.

المُنشئات Constructors في C++

المُنشئ constructor هو دالة عضوية خاصة تُستخدم لتهيئة الكائن عند إنشائه. يتم تنفيذها تلقائياً كلما أنشأت كائناً من الصنف.

يمتاز المُنشئ بعدة خصائص:

  • يحمل الاسم نفسه الذي يحمله الصنف.
  • لا يملك نوع إرجاع.
  • يُستخدم لضبط القيم الابتدائية للكائن.

مثال:

class Book {
    //..
public:
    Book() {
        // no return type and name same as the class name
        // define constructor here
    }
};

ويمكن أن يحتوي الصنف على أكثر من مُنشئ واحد، وهو ما يُعرف باسم function overloading، بحيث تختار اللغة المُنشئ المناسب وفق المعاملات الممررة.

المُخرّبات Destructors في C++

المُخرّب destructor هو دالة خاصة تُستدعى عندما ينتهي عمر الكائن، ووظيفتها الأساسية تحرير الموارد أو تنفيذ عمليات التنظيف اللازمة قبل إزالة الكائن من الذاكرة.

يُكتب المُخرّب باستخدام الرمز ~ متبوعاً باسم الصنف:

class Book {
    //..
public:
    // constructor
    //..
    ~Book() {
        // destroy object here
    }
};

في التطبيقات البسيطة قد لا تشعر بأهمية المُخرّب، لكن دوره يصبح حيوياً عندما يتعامل الكائن مع ملفات أو ذاكرة ديناميكية أو اتصالات خارجية.

متى تستخدم الأصناف فعلياً؟

استخدام classes لا يقتصر على الأمثلة التعليمية، بل يظهر في كل مشروع برمجي منظم تقريباً. يمكنك اللجوء إليها عندما تحتاج إلى:

  • تمثيل كيان واضح مثل كتاب أو مستخدم أو منتج.
  • جمع البيانات والسلوك المرتبطين بهذا الكيان في مكان واحد.
  • تقليل التكرار وتحسين تنظيم المشروع.
  • بناء أنواع مخصصة قابلة لإعادة الاستخدام.
  • تطبيق مبادئ التصميم الكائني بشكل سليم.

ملخص سريع لأهم مفاهيم الأصناف في C++

المفهوم الوظيفة
class تعريف نوع بيانات مخصص بواسطة المستخدم
object نسخة فعلية من الصنف داخل الذاكرة
member function دالة تعمل على بيانات الصنف أو كائناته
this مؤشر يشير إلى الكائن الحالي داخل الدالة العضوية
const function دالة لا تعدّل حالة الكائن
static function دالة مرتبطة بالصنف نفسه لا بكائن معين
friend آلية لمنح الوصول الخاص لدوال أو أصناف أخرى
constructor تهيئة الكائن عند إنشائه
destructor تنظيف الموارد عند انتهاء عمر الكائن

الخلاصة التقنية

تُعد الأصناف في C++ أكثر من مجرد وسيلة لتعريف أنواع جديدة؛ فهي أداة مركزية لبناء برامج منظمة وقابلة للتوسع. وعندما تفهم العلاقة بين class وobject، وتستوعب دور الدوال العضوية ومحددات الوصول والمُنشئات والمُخرّبات، ستتمكن من كتابة كود أقرب إلى الواقع وأكثر احترافية. من الناحية التقنية، إتقان هذه الأساسيات هو الخطوة التي تنقل المطور من كتابة تعليمات متفرقة إلى تصميم أنظمة برمجية واضحة وقابلة للصيانة.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *