التحويل في c++
المحتويات
- pd = dynamic_cast(&b); // wrong: base-to-derived
- using namespace std;
- int i,j;
- التحويل الضمني
- pd = dynamic_cast(pbb);
- b = (B) &d;
- dynamic_cast وreinterpret_cast وstatic_cast وconst_cast
- pd = dynamic_cast(pba);
- }
- B b = a;
- التحويل الديناميكي
- a = s;
- a = int(s); // functional notation
- (new_type) expression
- class A {};
- int a;
- }
- التحويل الصريح

في البداية، تحويل الأنواع في سي بلس بلس : وهي عبارة عن مجموعة طرق للتحويل من نوع إلى نوع معين في لغة ++C , مثلها مثل أي لغة أخرى , وبما أن لغة ++C لغة مميزة عن غيرها فلها طرق تحويل خاصة بها ,ويجب عليك كمبرمج لغة ++C أن تعرف كيف تتعامل مع هذه التحويلات بدقة لكي لا تكون برامجك عرضة للأخطاء التي أحيانا قد لاتكتشفها أثناء كتابة برنامجك . وتعرض الأقسام التالية جوانب أخرى من الموضوع.
pd = dynamic_cast(&b); // wrong: base-to-derived
وفي هذا الصدد، عندما تكون الفئة متعددة الأشكال polymorphic , فإن Dynamic_cast يقوم بحفص دقيق خلال وقت التشغيل للتأكد بأن القيمة المعادة صحيحة وصالحة للفئة المطلوبة ,مثال على ذلك :
- // dynamic_cast
- #include
- #include
في هذا الإطار، في الكود السابق ينتج المترجم خطأ بسبب التحويل الثاني لأن التحويل من فئة أساسية إلى فئة مشتقة غير مسموح .
إلا إذا كانت الفئة متعددة الأشكال (نمط من أنماط oop).
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;
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 <result;
- return 0;
التحويل الضمني
int a;
short s = 1000;
ومن ناحية أخرى، التحويل الضمني لايتطلب أي معامل , ويتم تنفيذها تلقائيا عندما يتم نسخ قيمة من نوع معين إلى نوع آخر موافق .
pd = dynamic_cast(pbb);
- if (pd==0) cout <<"Null pointer on second type-cast" <<endl;
- } catch (exception& e) {cout <<"Exception: " <<e.what;}
- return 0;
b = (B) &d;
وفي السياق ذاته، التحويل الصريح التقليدي يمكن أن يحول أي مؤشر إلى مؤشر آخر , ولكن بصرف النظر عن ذلك . إن استدعاء الدالة result قد تعطي خطأ في وقت التشغيل أو أنها تعطي قيمة غير متوقعة ,لأجل السطيرة على هذه التحويلات التي تتم بين الفئات ,لدينا أربع معاملات :
dynamic_cast وreinterpret_cast وstatic_cast وconst_cast
من جانب آخر، لديها صيغة خاصة فيها ,فيتم تمرير النوع داخل أقواس الزاوية ,وبعدها مباشرة يتم كتابة التعبير المراد تحويله بين قوسين .
- dynamic_cast (expression)
- reinterpret_cast (expression)
- static_cast (expression)
- const_cast (expression)
- أما التحويل الصريح فأن صيغته كالتالي :
pd = dynamic_cast(pba);
if (pd==0) cout <<"Null pointer on first type-cast" <<endl;
}
وعلى صعيد آخر، هذا الكود يقوم بتصريح مؤشر إلى الكائن B ,ولاحقًا يسند له مرجع من كائن آخر A غير متوافق معه بالنوع :
B b = a;
ومن جهة أخرى، في الكود السابق حدث تحويل بين كائنين A , B لأن مشيد الفئة B تحتوي على بارمتر من نوع A .لذلك التحويل الضمني مسموح فقط من A إلى B.
التحويل الديناميكي
وفي السياق ذاته، يمكن أن يستعمل التحويل الديناميكي فقط مع المؤشرات والمراجع إلتي تشير إلى الكائنات Object , الغرض منه هو ضمان أن تكون نتيجة التحويل صالحة وصحيحة بالنسبة للفئة المطلوبة ,ولذلك dynamic_cast دائما تعطيك نتيجة صحيحة عندما تريد التحويل بين الفئة المشتقة إلى واحدة من الفئات الأساسية.
- class CBase { };
- class CDerived: public CBase { };
- CBase b; CBase* pb;
- CDerived d; CDerived* pd;
- pb = dynamic_cast(&d); // ok: derived-to-base
a = s;
علاوةً على ذلك، كذلك يمكن أن يتضمن التحويل الضمني التحويل بين مشيدات الفئات (classes) إذا كان في إحد مشيد الفئة كائن للفئة الأخرى , مثال على ذلك :
ومن جهة أخرى، مع ذلك هذه التحويلات تعد غير دقيقة أي يمكن أحيانا أن يطلق المترجم رسائل تحذيرية ,ولتجنب ذلك يجب أن نستعمل التحوي الصريح explicit conversion .
من جانب آخر، هنا القيمة تم ترقيتها من short إلى int ,مع أننا لم نفوم باستخدام أي معامل للتحويل type_casting , هذا التحويل يسمى بالتحويل القياسي Implicit conversion ,وهو يؤثر في الأنواع الأساسية للبيانات , مثل تحويل الأنواع العديّدة (short to int, int to float, double to int) ويمكن تحويلهم كذلك إلى النوع المنطقي bool .
a = int(s); // functional notation
- class A
- {
- float x,y;
- };
- class B
- {
وعلى صعيد آخر، معاملات التحويل الصريح يمكن استخدامها لأغلب أنواع البيانات الأساسية , ولكن يمكن أن تطبق بشكل عشوائي على الكائنات ومؤشرات الكائنات ,أي يمكن أن تكون صحيحة من حيث التركيب ولكن تسبب في حدوث خطأ وقت التشغيل run-time :
(new_type) expression
new_type (expression)
وكل نوع من أنواع التحويل لديها مايميزها عن الآخر .
class A {};
class B { public: B (A a) {} };
A a;
int a;
a = (int) s; // c-like cast notation
}
- النتائج :
- Null pointer on second type-cast
- انظر كذلك
- لغة السي
- الكائنات في لغة ++C
- المتغيرات في لغة ++C
- أنواع البيانات في لغة ++C
التحويل الصريح
كذلك، يوجد نمطين للتحويل الصريح هو الوظيفي (الدالي) functional وc-like :
وعلى صعيد آخر، الكثير من التحويلات , خاصة تلك التي تعبر عن تفسيرات مختلفة في القيمة ,مثل هذه التحويلات تحتاج إلى تحويل صريح .
short s = 1000;
📝 هل في هذه المقالة خطأ؟
إذا وجدت معلومة تحتاج تصحيحاً أو إضافة، أو أردت حذف المقالة، أرسل لنا طلباً وسنراجعه.
ما رأيك في هذه المقالة؟