"typeid" مقابل "typeof" في C ++
سؤال
أنا أتساءل ما هو الفرق بين typeid
و typeof
في C ++. هذا ما أعرفه:
typeid
مذكور في الوثائق ل type_info الذي يتم تعريفه في ملف رأس C ++ TypeInfo.typeof
تم تعريفه في امتداد GCC لـ C وفي C ++ تعزيز مكتبة.
أيضًا ، هنا اختبار رمز الاختبار الذي قمت بإنشائه حيث اكتشفت ذلك typeid
لا يعيد ما كنت أتوقعه. لماذا ا؟
Main.cpp
#include <iostream>
#include <typeinfo> //for 'typeid' to work
class Person {
public:
// ... Person members ...
virtual ~Person() {}
};
class Employee : public Person {
// ... Employee members ...
};
int main () {
Person person;
Employee employee;
Person *ptr = &employee;
int t = 3;
std::cout << typeid(t).name() << std::endl;
std::cout << typeid(person).name() << std::endl; // Person (statically known at compile-time)
std::cout << typeid(employee).name() << std::endl; // Employee (statically known at compile-time)
std::cout << typeid(ptr).name() << std::endl; // Person * (statically known at compile-time)
std::cout << typeid(*ptr).name() << std::endl; // Employee (looked up dynamically at run-time
// because it is the dereference of a pointer
// to a polymorphic class)
}
انتاج:
bash-3.2$ g++ -Wall main.cpp -o main
bash-3.2$ ./main
i
6Person
8Employee
P6Person
8Employee
المحلول
لغة C ++ ليس لها شيء من هذا القبيل typeof
. يجب أن تنظر إلى بعض التمديد الخاص بالمترجمات. إذا كنت تتحدث عن دول مجلس التعاون الخليجي typeof
, ، ثم توجد ميزة مماثلة في C ++ 11 من خلال الكلمة الرئيسية decltype
. مرة أخرى ، لا يوجد شيء من هذا القبيل typeof
الكلمة الرئيسية.
typeid
هو مشغل لغة C ++ الذي يعيد معلومات التعريف في وقت التشغيل. يعيد أساسا أ type_info
الكائن ، الذي هو قابل للمساواة مع الآخرين type_info
أشياء.
لاحظ أن الخاصية المحددة الوحيدة التي تم إرجاعها type_info
الكائن له هو كونه مساواة وغير قابلة للأسمام ، أي type_info
يجب أن تقارن الكائنات التي تصف الأنواع المختلفة غير متساوٍ type_info
الكائنات التي تصف نفس النوع يجب أن تقارن متساوين. كل شيء آخر محدد للتنفيذ. الطرق التي تعيد "أسماء" مختلفة ليست مضمونة لإعادة أي شيء قابل للقراءة الإنسان ، وحتى غير مضمون لإعادة أي شيء على الإطلاق.
لاحظ أيضًا أن ما سبق على الأرجح (على الرغم من أن المعيار لا يبدو أنه يذكره بشكل صريح) typeid
إلى نفس النوع قد يعود مختلفًا type_info
الكائنات (والتي ، بالطبع ، لا يزال يتعين عليها مقارنة متساوية).
نصائح أخرى
الفرق الأساسي بين الاثنين هو ما يلي
- Typeof عبارة عن بنية وقت ترجمة وإرجاع النوع على النحو المحدد في وقت الترجمة
- TypeID هو بناء وقت التشغيل وبالتالي يقدم معلومات حول نوع وقت التشغيل للقيمة.
نوع المرجعية: http://www.delorie.com/gnu/docs/gcc/gcc_36.html
مرجع typeid: https://en.wikipedia.org/wiki/typeid
typeid
يمكن أن تعمل في وقت التشغيل ، وإرجاع كائن يصف نوع وقت التشغيل للكائن ، والذي يجب أن يكون مؤشرًا لكائن فئة ذات طرق افتراضية من أجل RTTI (معلومات نوع وقت التشغيل) لتخزينها في الفصل. يمكن أن يمنح أيضًا نوع وقت الترجمة للتعبير أو اسم النوع ، إن لم يتم إعطاؤه مؤشرًا إلى فئة مع معلومات نوع وقت التشغيل.
typeof
هو امتداد GNU ، ويمنحك نوع أي تعبير في وقت الترجمة. قد يكون هذا مفيدًا ، على سبيل المثال ، في إعلان المتغيرات المؤقتة في وحدات الماكرو التي يمكن استخدامها في أنواع متعددة. في C ++ ، عادة ما تستخدم قوالب في حين أن.
الإجابة على السؤال الإضافي:
لا يخرج رمز الاختبار التالي لـ TypeID اسم النوع الصحيح. ماالخطب؟
ليس هناك أي خطأ. ما تراه هو تمثيل السلسلة لاسم النوع. لا يجبر C ++ القياسي على المترجمين على إصدار الاسم الدقيق للفصل ، فالأمر متروك للمنفذ (بائع المترجم) لتحديد ما هو مناسب. باختصار ، الأسماء تصل إلى المترجم.
هذه أداتان مختلفتان. typeof
إرجاع نوع التعبير ، لكنه ليس قياسيًا. في C ++ 0x هناك شيء يسمى decltype
الذي يفعل نفس الوظيفة afaik.
decltype(0xdeedbeef) number = 0; // number is of type int!
decltype(someArray[0]) element = someArray[0];
بينما typeid
يستخدم مع أنواع الأشكال. على سبيل المثال ، دعنا نقول ذلك cat
مشتق animal
:
animal* a = new cat; // animal has to have at least one virtual function
...
if( typeid(*a) == typeid(cat) )
{
// the object is of type cat! but the pointer is base pointer.
}
يوفر TypeID نوع البيانات في وقت التشغيل ، عند الطلب. Typedef هو بنية وقت الترجمة التي تحدد نوعًا جديدًا كما هو مذكور بعد ذلك. لا يوجد أي نوع في إخراج C ++ يظهر على أنه (يظهر كتعليقات منقوشة):
std::cout << typeid(t).name() << std::endl; // i
std::cout << typeid(person).name() << std::endl; // 6Person
std::cout << typeid(employee).name() << std::endl; // 8Employee
std::cout << typeid(ptr).name() << std::endl; // P6Person
std::cout << typeid(*ptr).name() << std::endl; //8Employee
يمكنك استخدام تشكيل Boost لإنجاز اسم جميل المظهر:
#include <boost/units/detail/utility.hpp>
وشيء مثل
To_main_msg_evt ev("Failed to initialize cards in " + boost::units::detail::demangle(typeid(*_IO_card.get()).name()) + ".\n", true, this);