فئة أم بنية في C++: متى تختار أيهما؟ تحليل السؤال الرئيسي

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

فئة أم بنية في C++: الجدل الأبدي

\n\n

تخيل موقفًا: أنت تكتب كودًا بلغة C++، وتحتاج إلى إنشاء نوع بيانات جديد. يتبادر إلى ذهنك على الفور سؤال: «متى يجب استخدام class، ومتى يجب استخدام struct؟». هذا السؤال لا يقلق المبتدئين فقط - بل حصد آلاف المشاهدات وعشرات المناقشات الساخنة على Stack Overflow. وهذا ليس مفاجئًا: ففي C++، هاتان الكلمتان الرئيسيتان تقومان بنفس الشيء للوهلة الأولى، ولكن مع فروق دقيقة.

\n\n

في هذه المقالة، سنحسم الأمر مرة واحدة وإلى الأبد، ونفهم الفرق الحقيقي بين class و struct، ومتى نختار أيهما، وكيف لا نقع في الخطأ. هيا بنا!

\n\n

الفرق الرئيسي: معدّلات الوصول الافتراضية

\n\n

إذا كنت تعتقد أن class و struct هما كيانان مختلفان تمامًا، فأنت مخطئ. في C++، الاختلاف الجوهري الوحيد بينهما هو معدّل الوصول الافتراضي:

\n\n
    \n
  • struct: جميع الأعضاء (الحقول والدوال) تكون افتراضيًا public.
  • \n
  • class: جميع الأعضاء تكون افتراضيًا private.
  • \n
\n\n

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

\n\n

مثال مع struct

\n
struct Point {\n    int x;\n    int y;\n};\n\n// يمكن الوصول مباشرة\nPoint p;\np.x = 10;\np.y = 20;
\n\n

مثال مع class

\n
class Point {\n    int x;  // private افتراضيًا!\n    int y;\npublic:\n    void setX(int val) { x = val; }\n    void setY(int val) { y = val; }\n};\n\nPoint p;\n// p.x = 10; // خطأ! x خاص (private)\np.setX(10);   // هذا مسموح به
\n\n

كما ترى، الفرق فقط في كيفية إخفاء البيانات «افتراضيًا». لكن هذا لا يعني أن الاختيار بين class و struct هو مسألة ذوق. هناك ممارسات متعارف عليها.

\n\n

متى تختار struct؟

\n\n

في مجتمع C++، هناك إجماع غير مكتوب: struct - للبيانات البسيطة. استخدم struct عندما يكون النوع الخاص بك مجرد مجموعة من الحقول العامة بدون منطق معقد. الأمثلة الكلاسيكية:

\n\n
    \n
  • إحداثيات نقطة (x, y)
  • \n
  • لون RGB (r, g, b)
  • \n
  • إعدادات (width, height, title)
  • \n
  • نتيجة عملية (success, errorMessage)
  • \n
\n\n

في مثل هذه الحالات، لا داعي لإخفاء البيانات - فهي عامة بطبيعتها. struct يجعل الكود أنظف وأقصر. بالإضافة إلى ذلك، struct مناسب تمامًا لـ أنواع POD (Plain Old Data) - الهياكل التي يمكن نسخها باستخدام memcpy بسيط.

\n\n

مثال على الاستخدام الصحيح لـ struct

\n
struct Vector2 {\n    float x;\n    float y;\n    \n    // يمكن إضافة دوال بسيطة\n    float length() const {\n        return std::sqrt(x*x + y*y);\n    }\n};\n\n// نستخدمه كحاوية بيانات بسيطة\nVector2 v = {3.0f, 4.0f};\nstd::cout << v.length(); // 5.0
\n\n

لاحظ: حتى إذا كان struct يحتوي على دوال، فهذا أمر طبيعي. المهم أن تبقى الحقول عامة، ولا يتطلب النوع منطقًا معقدًا للحفاظ على الثوابت (invariants).

\n\n

متى تختار class؟

\n\n

Class هو الخيار الافتراضي للكائنات الكاملة. استخدم class عندما:

\n\n
    \n
  • لديك منطق معقد يتطلب التغليف (encapsulation).
  • \n
  • تريد التحكم الصارم في كيفية تغيير البيانات.
  • \n
  • النوع الخاص بك يحتوي على ثوابت (invariants) (مثل «العمر لا يمكن أن يكون سالبًا»).
  • \n
  • تستخدم الوراثة، الدوال الافتراضية، تعدد الأشكال.
  • \n
\n\n

المثال الكلاسيكي هو فئة «حساب بنكي». لا ينبغي أن يكون الرصيد عامًا، وإلا فقد يقوم شخص ما بتعيين قيمة سالبة عن طريق الخطأ.

\n\n

مثال على الاستخدام الصحيح لـ class

\n
class BankAccount {\nprivate:\n    double balance;\n    std::string owner;\n    \npublic:\n    BankAccount(const std::stri                

المدونات

توصيات الكتب