النطاقات (Scopes) المتغيرات العامة (Global variables) إذا أردت التصريح عن نسخة واحدة من متغير ما، وكانت هذه النسخة متاحة للوصول في عدة ملفات مصدرية (source files)، فمن الممكن أن نجعلها في النطاق العام (global scope) باستخدام الكلمة المفتاحية extern، فهي تخبر المصرِّف بوجود تعريف لهذا المتغ…
تُعرف اللغتان C و C++‎ بانّ أداءهما عال جدًّا - ويُعزى ذلك في الغالب إلى إمكانية التخصيص المكثّف للشيفرة، إذ يُسمح للمستخدم بتحسين الأداء عبر اختيار بنية الشيفرة وكيفية تنفيذها. وإن أردت تحسين الشيفرة فمن المهم أن تفهمها وتعرف كيفية استخدامها. وتشمل بعض أخطاء التحسين الشائعة ما يلي: التح…
يقضي مطوّرو C++‎ الكثير من وقتهم في تنقيح الأخطاء (debugging)، ويهدف هذا المقال إلى مساعدتك في هذه المهمة وإعطائك بعض التقنيات المفيدة، لكن لا تتوقع قائمة شاملة للمشاكل وحلولها التي تدعمها هذه الأدوات. اختبار الوحدات في C++‎ يسعى اختبار الوحدات (Unit testing) إلى التحقق من صحّة وسلامة وحدا…
ينبغي تصريف البرامج المكتوبة بلغة C++‎ قبل أن تتمكن تلك البرامج من العمل، وستجد مجموعة كبيرة ومتنوّعة من برامج التصريف أو المصرِّفات (compilers) المتاحة والمناسبة لنظام التشغيل الذي تعمل به. التصريف بواسطة GCC التصريف دون تحسين مفيد في المراحل الأولى من التطوير والتنقيح، على الرغم من أنّ خ…
محدّدات أصناف التخزين هي كلمات مفتاحية يمكن استخدامها في التصريحات، ولا تؤثر على نوع التصريح لكنها تعدّل الطريقة التي تُخزّن بها الكيانات. extern محدّدُ صنف التخزين ‎extern‎ يستطيع التصريحَ بإحدى الطرق الثلاث التالية، وذلك وفقًا للسياق، فمثلًا: يمكن استخدامه للتصريح عن متغيّر دون تعر…
إدارة الموارد هي إحدى أصعب الأشياء في C و C++‎، لكن C++‎ توفّر لنا العديد من الطرق التي نصمم بها إدارة الموارد في برامجنا، وسنحاول في هذا المقال أن نشرح بعض هذه الطرق. تقنية RAII: تخصيص الموارد يكافئ التهيئة تقنية RAII وتدعى اكتساب أو تخصيص الموارد هي تهيئة (Resource Acquisition Is Initial…
لغة C++‎، على غرار C، لها تاريخ طويل ومتنوّع بخصوص سير العمل التصريفي وعمليات البناء. واليوم، لدى لغة C++‎ العديد من أنظمة البناء التي تُستخدَم لتصريف البرامج لعدة منصات أحيانًا داخل نظام بناء واحد. وسننظر في هذا الدرس في بعض أنظمة البناء ونحلّلها. إنشاء بيئة بناء باستخدام CMake ينشئ CMake…
الصحة الثباتية (Const Correctness) أسلوب لتصميم الشيفرات، يعتمد على فكرة أنّه لا ينبغي أن تُتاح إمكانية تعديل نسخة معيّنة -على سبيل المثال الحق في الكتابة- إلّا للشيفرَات التي تحتاج إلى تعديل تلك النسخة، وبالمقابل، فإنّ أيّ شيفرة لا تحتاج إلى تعديل نُسخة ما لن تملك القدرة على تعديلها، أي سيكون لها…
سوف نستعرض في هذا الدرس بعض الأمثلة على كيفية التعامل مع خادم العميل (Client server). مثال Hello TCP Client هذا البرنامج مكمّل لبرنامج Hello TCP Server، ويمكنك تشغيل أي منهما للتحقق من صلاحيتهما. انظر شيفرة المثال فيما يلي: #include #include #include #include #include #include #in…
تطبيقات على التعاود يمكن استعمال التعاود في الكثير من التطبيقات المفيدة إذ يساعدنا على تبسيط الشيفرة ويعطيها قوة وفعالية على عكس لو لم نعتمد على مفهوم التعاود وإليك بعض هذه التطبيقات مع شيفراتها. حساب تسلسلات فيبوناتشي Fibonnaci sequence هذه هي الطريقة الأبسط لاستخدام التكرارية للحصول …
السمة [[fallthrough]] الإصدار ≥ C++‎ 17 عند إنهاء تعليمة case بكلمة switch ستنفَّذ الشيفرة التي تليها، وإن أردت منع هذا السلوك، فاستخدم تعليمة ‎‎break‎‎. يُسمّى هذا السلوك بـ "السقطة" (fallthrough)، وقد ينجم عنه أخطاء غير مقصودة، لذا تطلق العديد من المُصرِّفات والمحلّلات الساكنة (static an…
‎constexpr‎ هي كلمة مفتاحية يمكن استخدامها مع متغيّر لجعل قيمته تعبيرًا ثابتًا (constant expression)، أو دالةً لأجل استخدامها في التعبيرات الثابتة، أو (منذ C++‎ 17) تعليمة if حتى يُصرَّف فرع واحد فقط من فروعها. المصادقة عبر الدالة static_assert تقتضي المصادقات (Assertations) وجوب التحقق من…
نماذج الذاكرة إن حاوَلَت عدّة خيوط الوصول إلى نفس الموضع من الذاكرة، فستدخل في تسابق على البيانات (data race) إذا تسبب عملية واحدة على الأقل من العمليات المُنفّذة في تعديل البيانات -تُعرف باسم عمليات التخزين store operation-، وتتسبّب سباقات البيانات تلك في سلوك غير معرَّف. ولكي نتجنبها، امنع ا…
القيم الثنائية مصنفة النوع المُعرّفة من المستخدم (Self-made user-defined literal for binary) رغم إمكانية كتابة عدد ثنائي في C++‎ 14 على النحو التالي: int number =0b0001'0101; // ==21 إلا أننا في الأسطر التالية سنستعرض مثالًا مشهورًا يوفّر طريقة أخرى ذاتية التنفيذ للأعداد الثنائية. لاحظ أن…
سنستعرض في هذا الدرس بعض أنماط التصميم الشهيرة في C++‎ ثم سنتطرق سريعًا إلى مفهوم إعادة التصميم (Refactoring) والنمط Goto Cleanup المتَّبع. نمط المحوِّل (Adapter Pattern) يتيح نمط المحوِّل للأصناف غير المتوافقة أن تعمل معًا، والسبب الأساسي في استخدامه تكمن في أنّه يمكّن المطوّرين من إعادة …
إعادة التوجيه التامة (Perfect Forwarding) الدوالّ المُنتِجة (Factory functions) لنفترض أنّنا نرغب في كتابة دالّة منتِجة تقبل قائمة عشوائية من الوسائط، ثمّ تمرّر تلك الوسائط دون تعديل إلى دالّة أخرى. إن دالة ‎make_unique‎ هي مثال على مثل هذه الدوال، وتُستخدَم لاستنساخ نسخة جديدة من ‎T‎ بأما…
ينصّ المعيار على ضرورة نسخ الكائنات أو نقلها في بعض المواضع من أجل تهيئتها، وإهمال النسخ (Copy elision) الذي يسمى أحيانًا تحسين القيمة المُعادة (return value optimization) هو تحسينٌ يسمح للمُصرِّف بتجنّب النسخ أو النقل في ظروف معيّنة، حتى لو كان المعيار ينصّ على ذلك. انظر الدالة التالية: std::s…
تمكّن الكلمة المفتاحية ‎auto‎ من الاستنتاج التلقائي لنوع متغيّر معيّن، وهي مناسبة بشكل خاص عند التعامل مع أسماء الأنواع الطويلة: std::map < std::string, std::shared_ptr < Widget > > table; // C++98 std::map < std::string, std::shared_ptr < Widget > > ::iterator i = table.find("42"); // C++11/14…
دلالات النقل هي وسيلة لنقل كائن إلى آخر في C++‎، عبر إفراغ الكائن القديم، وتبديل محتوياته بمحتويات الكائن الجديد. ولفهم دلالات النقل، من الضروري فهم المقصود بالمرجع اليميني (rvalue reference). وهي، أي المراجع اليمينية (‎T&&‎ حيث T يمثّل نوع الكائن) لا تختلف كثيرًا عن المراجع العادية (‎T&‎، يُطلق ع…
ما المقصود بالسلوك غير المعرَّف (undefined behavior أو UB)؟ وفقًا لمعيار ISO C++‎ (الفقرة 1.3.24، N4296)، فهو: هذا يعني أنّه عندما يواجه البرنامج سلوكًا غير معرَّف، فإنّه يُسمَح له بفعل ما يريد. هذا قد يعني غالبًا التوقف عنا العمل، ولكنّه قد يعني تجاهله وعدم فعل أيّ شيء، أو قد يعمل البرنامج ب…