Как я могу получить имя класса из объекта C ++?

Можно ли получить имя объекта тоже?

#include<cstdio>

class one {
public:
int no_of_students;
one() { no_of_students = 0; }
void new_admission() { no_of_students++; }
};

int main() {
one A;
for(int i = 0; i < 99; i++) {
A.new_admission();
}
cout<<"class"<<[classname]<<" "<<[objectname]<<"has "<<A.no_of_students<<" students";
}

где я могу получить имена, что-то вроде

[classname] = A.classname() = one
[objectname] = A.objectname() = A

Предоставляет ли C ++ какой-либо механизм для достижения этой цели?

38

Решение

Вы можете отобразить имя переменной с помощью препроцессора. Например

#include <iostream>
#define quote(x) #x
class one {};
int main(){
one A;
std::cout<<typeid(A).name()<<"\t"<< quote(A) <<"\n";
return 0;
}

выходы

3one    A

на моей машине. # изменяет токен в строку, после предварительной обработки строка

std::cout<<typeid(A).name()<<"\t"<< "A" <<"\n";

Конечно, если вы делаете что-то вроде

void foo(one B){
std::cout<<typeid(B).name()<<"\t"<< quote(B) <<"\n";
}
int main(){
one A;
foo(A);
return 0;
}

ты получишь

3one B

поскольку компилятор не отслеживает все имена переменных.

Как это происходит в gcc, результатом typeid (). Name () является искаженное имя класса, чтобы получить демаркированная версия использование

#include <iostream>
#include <cxxabi.h>
#define quote(x) #x
template <typename foo,typename bar> class one{ };
int main(){
one<int,one<double, int> > A;
int status;
char * demangled = abi::__cxa_demangle(typeid(A).name(),0,0,&status);
std::cout<<demangled<<"\t"<< quote(A) <<"\n";
free(demangled);
return 0;
}

что дает мне

one<int, one<double, int> > A

Другие компиляторы могут использовать разные схемы именования.

59

Другие решения

использование typeid(class).name

// иллюстративный код, предполагающий, что все включает / пространства имен и т. д.

#include <iostream>
#include <typeinfo>
using namespace std;

struct A{};
int main(){
cout << typeid(A).name();
}

Важно помнить, что это
дает реализацию определенных имен.

Насколько я знаю, нет способа получить имя объекта во время выполнения надежно, например, «А» в вашем коде.

РЕДАКТИРОВАТЬ 2:

#include <typeinfo>
#include <iostream>
#include <map>
using namespace std;

struct A{
};
struct B{
};

map<const type_info*, string> m;

int main(){
m[&typeid(A)] = "A";         // Registration here
m[&typeid(B)] = "B";         // Registration here

A a;
cout << m[&typeid(a)];
}
15

Вы хотите, чтобы [classname] было ‘one’, а [objectname] было ‘A’?

Если это так, это невозможно. Эти имена являются только абстракциями для программиста и фактически не используются в генерируемом двоичном коде. Вы можете присвоить классу статическую переменную classname, которую вы устанавливаете в ‘one’, и обычную переменную namename объекта, которую вы присваиваете напрямую, через метод или конструктор. Затем вы можете запросить эти методы для имен классов и объектов.

8

Чтобы получить имя класса без искажений, вы можете использовать FUNC макрос в конструкторе:

class MyClass {
const char* name;
MyClass() {
name = __func__;
}
}
6

Вы можете попробовать использовать «TypeId».

Это не работает для имени объекта, но вы знаете имя объекта, поэтому вам просто нужно где-то его сохранить. Компилятору не важно, что вы называете объектом.

Однако стоит помнить, что вывод typeid является специфической для компилятора вещью, поэтому даже если он производит то, что вам нужно, на текущей платформе, он может не работать на другой. Это может или не может быть проблемой для вас.

Другое решение состоит в том, чтобы создать какую-то оболочку шаблона, в которой вы сохраняете имя класса. Затем вам нужно использовать частичную специализацию, чтобы она возвращала правильное имя класса для вас. Это имеет преимущество рабочего времени компиляции, но значительно сложнее.

Изменить: Быть более явным

template< typename Type > class ClassName
{
public:
static std::string name()
{
return "Unknown";
}
};

Тогда для каждого класса somethign lik следующее:

template<> class ClassName<MyClass>
{
public:
static std::string name()
{
return "MyClass";
}
};

Что может быть даже макросом, как показано ниже:

#define DefineClassName( className ) \
\
template<> class ClassName<className> \
{ \
public: \
static std::string name() \
{ \
return #className; \
} \
}; \

Позволяет вам просто сделать

DefineClassName( MyClass );

Наконец, чтобы получить имя класса, вы должны сделать следующее:

ClassName< MyClass >::name();

Edit2: Если продолжить, вам нужно будет поместить этот макрос «DefineClassName» в каждый создаваемый вами класс и определить функцию «classname», которая будет вызывать функцию статического шаблона.

Edit3: И подумать об этом … Очевидно, что поначалу плохо публиковать сообщения утром, так как вы можете просто определить функцию-член «classname ()» следующим образом:

std::string classname()
{
return "MyClass";
}

который может быть макроопределен следующим образом:

DefineClassName( className ) \
std::string classname()  \
{ \
return #className; \
}

Тогда вы можете просто уронить

DefineClassName( MyClass );

в класс, как вы определяете это …

4

Просто напишите простой шаблон:

template<typename T>
const char* getClassName(T) {
return typeid(T).name();
}

struct A {} a;

void main() {
std::cout << getClassName(a);
}
3

Улучшение для ответа @Chubsdad,

//main.cpp

using namespace std;

int main(){
A a;
a.run();
}

//A.h
class A{
public:
A(){};
void run();
}

//A.cpp
#include <iostream>
#include <typeinfo>
void A::run(){
cout << (string)typeid(this).name();
}

Который напечатает:

class A*
2
По вопросам рекламы [email protected]