Получение программного кода класса С++
Мне было интересно, возможно ли в С++ получить имя класса в строковой форме без необходимости жестко указывать его в переменную или getter. Я знаю, что ни одна из этих данных фактически не используется во время выполнения, поэтому она недоступна, но есть ли какие-либо макросы, которые могут быть созданы для создания этой функции?
Изменить: Может быть полезно заметить, что я на самом деле пытаюсь получить имя производного класса, и я использую Visual С++ 2008 Express Edition.
Ответы
Ответ 1
Вы можете использовать typeid
:
#include <typeinfo>
cout << typeid(obj).name() << endl;
Однако это обескураживает, поскольку формат не стандартизирован и может различаться между разными компиляторами (или даже разными версиями одного и того же компилятора).
Ответ 2
Если вы просто хотите проверить, есть ли у него определенный класс, то
typeid(obj) == typeid(CSubClass)
всегда будет работать независимо от реализаций.
В противном случае удобно объявить:
virtual const char* classname() { return "CMyClass";}
и реализовать для каждого подкласса.
Ответ 3
Тип typeid(obj).name()
всегда дает тип переменной, как она была объявлена, а не фактический тип (класс) объекта. Если переменная obj назначена экземпляру подкласса класса, для которого было объявлено obj, typeid, к сожалению, этого не раскрывает.
Ответ 4
Как насчет этого,
Протестировано в Windows 10 с использованием Visual Studio 2019 (v142).
#include <iostream>
#include <typeinfo>
#include <string>
/**
@author blongho
@fn template<typename Object> std::string classNameOf()
@brief Determine the class name of an object
@tparam Object Type of the object.
@returns A name of the class
@date 2019-09-06
*/
template<typename Object>
std::string classNameOf() {
std::string name = typeid(Object).name(); //* user defined types gives "class Type"*\
size_t spacePosition = name.find_first_of(" ");
if (spacePosition != std::string::npos) {
return name.substr(spacePosition + 1, name.length());
}
return name; // mostly primitive types
}
class Person {
private:
/* data */
public:
Person() {};
~Person() {};
};
class Data
{
private:
/* data */
public:
Data() {};
~Data() {};
};
struct Type {};
int main() {
std::cout << "Class name of Person() is \"" << classNameOf<Person>() << "\"\n";
std::cout << "Class name of Data() is \"" << classNameOf<Data>() << "\"\n";
std::cout << "Class name of Data() is \"" << classNameOf<Type>() << "\"\n";
std::cout << "Class name of double is \"" << classNameOf<double>() << "\"\n";
std::cout << "Class name of std::string is \"" << classNameOf<std::string>() << "\"\n";
std::cout << "Class name of int is \"" << classNameOf<int>() << "\"\n";
std::cout << "Class name of float is \"" << classNameOf<float>() << "\"\n";
std::cout << "Class name of char is \"" << classNameOf<char>() << "\"\n";
return 0;
}
Output
Class name of Person() is "Person"
Class name of Data() is "Data"
Class name of Data() is "Type"
Class name of double is "double"
Class name of std::string is "std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >"
Class name of int is "int"
Class name of float is "float"
Class name of char is "char"
В Ubuntu 18.04,
g++ -o test src/main.cpp
./test
Class name of Person() is "6Person"
Class name of Data() is "4Data"
Class name of Data() is "4Type"
Class name of double is "d"
Class name of std::string is "NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE"
Class name of int is "i"
Class name of float is "f"
Class name of char is "c"