2009-06-21 4 views
53

Мне было интересно, можно ли в C++ получить имя класса в форме строки без необходимости его жесткого кодирования в переменную или getter. Я знаю, что ни одна из этих данных фактически не используется во время выполнения, поэтому она недоступна, но есть ли какие-либо макросы, которые могут быть созданы для создания этой функции?Извлечение имени класса C++ программно

Редактировать: Может быть полезно заметить, что я на самом деле пытаюсь получить имя производного класса, и я использую Visual C++ 2008 Express Edition.

+0

Поскольку это зависит от компилятора, с каким компилятором вы работаете? –

+0

Я использую visual C++ 2008 express, и я думаю, было бы полезно отметить, что я действительно пытаюсь получить имя производного класса – Morgan

ответ

84

Вы можете использовать typeid:

#include <typeinfo> 
cout << typeid(obj).name() << endl; 

Однако это не рекомендуется, поскольку формат не стандартизированы и могут отличаться между различными компиляторами (или даже разных версий одного и того же компилятора).

+0

Интересно, я не знал об этом. Кажется, это работает очень хорошо. Это дает мне немного больше текста, чем я хотел в ответ, но, похоже, он работает очень хорошо. Благодаря! – Morgan

+0

Будет ли эта работа виртуальными методами в классе? Я, хотя RTTI не работает в этом случае. Я предполагаю, что пока у вас есть виртуальный деструктор, с вами все будет в порядке. – LeopardSkinPillBoxHat

+5

@LeopardSkinPillBoxHat: Да, это сработает (см. §5.2.8/3 и 4). Это распространенное заблуждение, что 'typeid' будет работать только с полиморфными типами, вероятно, из-за сходства с функциями RTTI. - Фактически, использование 'typeid' на статических типах не требуется и не использует RTTI. Оператор оценивается во время компиляции, и результат компилируется (строго говоря, это деталь реализации, но это единственная нормальная реализация). –

35

Если вы просто хотите проверить, если это определенный класс, то

typeid(obj) == typeid(CSubClass) 

всегда будет работать независимо от реализации.

В противном случае, удобный способ заявить:

virtual const char* classname() { return "CMyClass";} 

и реализовать в подклассе.

+0

Отличное решение. Легко, просто, работает - на каждой версии :) –

+2

Легко, просто, компилируется. Неправильно, к сожалению. 'typeid()' возвращает указатель 'typeinfo *', указатель. Если два указателя 'typeinfo * 'равны, они относятся к одному типу, но если они не равны, они все равно могут ссылаться на один и тот же тип. Вот почему существует класс 'std :: type_index' с правильной семантикой. 'std :: type_index (typeid (obj)) == std :: type_index (typeid (CSubClass))' будет true ** тогда и только тогда, когда ** оба типа равны. – MSalters

8

Тип typeid (obj) .name() всегда задает тип переменной, как он был объявлен, а не фактический тип (класс) объекта. Если переменная obj присваивается экземпляру подкласса класса, объявленному obj, typeid не показывает этого, к сожалению.

+7

Использование GCC 4.7.3, используя typeid (* somePtr) .name() дает мне имя конкретных классов. – notlesh

+3

Я столкнулся с той же проблемой, но комментарий @ stephelton заставило меня понять, что я вызывал его вместо указателя вместо фактического объекта или ссылки, и он возвращал тип указателя! Просто добавив '*' исправленное все. –

+0

Подтверждение обоих приведенных выше комментариев для VS. После 'BaseClass * ptr = new SubClass;' Я нахожу 'typeid (ptr) .name()' yields 'class BaseClass *', а 'typeid (* ptr) .name()' дает 'class SubClass'. –

Смежные вопросы