التحويل في c++

تحويل الأنواع في سي بلس بلس : (بالإنجليزية: type casting) وهي عبارة عن مجموعة طرق للتحويل من نوع إلى نوع معين في لغة ++C , مثلها مثل أي لغة أخرى , وبما أن لغة ++C لغة مميزة عن غيرها فلها طرق تحويل خاصة بها ,ويجب عليك كمبرمج لغة ++C أن تعرف كيف تتعامل مع هذه التحويلات بدقة لكي لا تكون برامجك عرضة للأخطاء التي أحيانا قد لاتكتشفها أثناء كتابة برنامجك .

التحويل الضمني

التحويل الضمني (بالإنجليزية: Implicit conversion) لايتطلب أي معامل , ويتم تنفيذها تلقائيا عندما يتم نسخ قيمة من نوع معين إلى نوع آخر موافق .
short s = 1000;int a;a = s;
هنا القيمة تم ترقيتها من short إلى int ,مع أننا لم نفوم باستخدام أي معامل للتحويل type_casting , هذا التحويل يسمى بالتحويل القياسي Implicit conversion ,وهو يؤثر في الأنواع الأساسية للبيانات , مثل تحويل الأنواع العديّدة (short to int, int to float, double to int) ويمكن تحويلهم أيضا إلى النوع المنطقي bool .
مع ذلك هذه التحويلات تعد غير دقيقة أي يمكن أحيانا أن يطلق المترجم رسائل تحذيرية ,ولتجنب ذلك يجب أن نستخدم التحوي الصريح explicit conversion .
أيضا يمكن أن يتضمن التحويل الضمني التحويل بين مشيدات الفئات (classes) إذا كان في إحد مشيد الفئة كائن للفئة الأخرى , مثال على ذلك :
class A {};class B { public: B (A a) {} };A a;B b = a;
في الكود السابق حدث تحويل بين كائنين A , B لأن مشيد الفئة B تحتوي على بارمتر من نوع A .لذلك التحويل الضمني مسموح فقط من A إلى B.

التحويل الصريح

(بالإنجليزية: Explicit conversion) العديد من التحويلات , خاصة تلك التي تعبر عن تفسيرات مختلفة في القيمة ,مثل هذه التحويلات تحتاج إلى تحويل صريح .
يوجد نمطين للتحويل الصريح هو الوظيفي (الدالي) functional وc-like :
short s = 1000;int a;a = (int) s; // c-like cast notationa = int(s); // functional notation
معاملات التحويل الصريح يمكن استخدامها لمعظم أنواع البيانات الأساسية , ولكن يمكن أن تطبق بشكل عشوائي على الكائنات ومؤشرات الكائنات ,أي يمكن أن تكون صحيحة من حيث التركيب ولكن تسبب في حدوث خطأ وقت التشغيل run-time :
class A{
    float x,y;};class B{
    int i,j;public:
    B (int a, int b) { i = a; j = b; }
    int result() { return i + j; }};int main(){ 
    A d;
    B *b;
    b = (B) &d;      //Error
    cout <<b->result();
    return 0;}
هذا الكود يقوم بتصريح مؤشر إلى الكائن B ,وبعد ذلك يسند له مرجع من كائن آخر A غير متوافق معه بالنوع : 
b = (B) &d;
التحويل الصريح التقليدي يمكن أن يحول أي مؤشر إلى مؤشر آخر , ولكن بصرف النظر عن ذلك . إن استدعاء الدالة result قد تعطي خطأ في وقت التشغيل أو أنها تعطي قيمة غير متوقعة ,لأجل السطيرة على هذه التحويلات التي تتم بين الفئات ,لدينا أربع معاملات :
dynamic_cast وreinterpret_cast وstatic_cast وconst_cast
لديها صيغة خاصة فيها ,فيتم تمرير النوع داخل أقواس الزاوية <> ,وبعدها مباشرة يتم كتابة التعبير المراد تحويله بين قوسين .
dynamic_cast <new_type> (expression)reinterpret_cast <new_type> (expression)static_cast <new_type> (expression)const_cast <new_type> (expression)
أما التحويل الصريح فأن صيغته كالتالي :
(new_type) expressionnew_type (expression)
وكل نوع من أنواع التحويل لديها مايميزها عن الآخر .

التحويل الديناميكي

(بالإنجليزية: dynamic_cast) يمكن أن يستخدم التحويل الديناميكي فقط مع المؤشرات والمراجع إلتي تشير إلى الكائنات Object , الغرض منه هو ضمان أن تكون نتيجة التحويل صالحة وصحيحة بالنسبة للفئة المطلوبة ,ولذلك dynamic_cast دائما تعطيك نتيجة صحيحة عندما تريد التحويل بين الفئة المشتقة إلى واحدة من الفئات الأساسية.
class CBase { };class CDerived: public CBase { };CBase b; CBase* pb;CDerived d; CDerived* pd;pb = dynamic_cast<CBase*>(&d); // ok: derived-to-basepd = dynamic_cast<CDerived*>(&b); // wrong: base-to-derived
في الكود السابق ينتج المترجم خطأ بسبب التحويل الثاني لأن التحويل من فئة أساسية إلى فئة مشتقة غير مسموح .
إلا إذا كانت الفئة متعددة الأشكال (نمط من أنماط oop).
عندما تكون الفئة متعددة الأشكال polymorphic , فإن Dynamic_cast يقوم بحفص دقيق خلال وقت التشغيل للتأكد بأن القيمة المعادة صحيحة وصالحة للفئة المطلوبة ,مثال على ذلك :
// dynamic_cast#include <iostream>#include <exception>using namespace std;class CBase { virtual void dummy() {} };class CDerived: public CBase { int a; };int main () {
  try {
    CBase * pba = new CDerived;
    CBase * pbb = new CBase;
    CDerived * pd;

    pd = dynamic_cast<CDerived*>(pba);
    if (pd==0) cout <<"Null pointer on first type-cast" <<endl;

    pd = dynamic_cast<CDerived*>(pbb);
    if (pd==0) cout <<"Null pointer on second type-cast" <<endl;

  } catch (exception& e) {cout <<"Exception: " <<e.what();}
  return 0;}
النتائج :
Null pointer on second type-cast