Как получить имя класса полиморфного объекта С++ с помощью WIN32 Debug Info API?

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

Для целей отладки/диагностики/разработки я хочу написать функцию для получения экземпляра имени класса объекта С++ в качестве вывода и в качестве ввода указателя на базовый класс.

Например:

const char* GetNameOfInstanciatedClassByVoidPtr(void* pBaseClassOrInstanciatedClass);

class B { public: virtual void Init (){
  assert(StringIsEqual(GetNameOfInstanciatedClassByVoidPtr(this), "C")); } };
class C : B {} c; c.Init(); 

Пожалуйста, предоставьте решение для реализации функции GetNameOfInstanciatedClassByVoidPtr.

Итак, вопрос: что требуется lib/header/function? Я думаю, API для информации об отладке win32 поможет?

Написание виртуальных функций, возвращающих строки или type_info, в моей ситуации неприемлемо.

Как я уже говорил: это только для целей диагностики/отладки/разработки, НЕ для производственного кода, поэтому, пожалуйста, избегайте дискуссий о целях чистого кода. Я также мог бы собирать информацию вручную, но, поскольку это около 260 классов, я мог бы работать быстрее. ;)

EDIT: в первой версии вопроса у меня была функция GetNameOfInstanciatedClassByVoidPtr, вызываемая в конструкторе, но я заметил, что информация еще недоступна во время конструктора. Поэтому я помещаю его в метод Init, который всегда вызывается. В этом методе отладчик показывает имя экземпляра класса, поэтому, если я помещу функцию GetNameOfInstanciatedClassByVoidPtr в мой метод инициализации, информация может быть получена.


person seebee    schedule 29.07.2021    source источник
comment
Отладчик win32 показывает имя рассматриваемого класса в окне инспектора из void* или из B*?   -  person Jarod42    schedule 29.07.2021
comment
отладчик использует файл pdb. взять указатель на виртуальную таблицу. посмотрите, какое имя символа по этому адресу. имя разбора. и т.д. все это очень не просто   -  person RbMm    schedule 29.07.2021
comment
Эта информация передается компоновщиком в файл базы данных программы (PDB). Вы можете использовать интерфейс отладки. Получите доступ к SDK, чтобы запросить оттуда информацию.   -  person IInspectable    schedule 29.07.2021


Ответы (1)


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

#include <iostream>
#include <typeinfo>

struct A {
    virtual void printName(){
        std::cout << typeid(*this).name() << "\n";
    }
    virtual ~A() = default;
};
struct C : A{};

int main() {
    C c;
    c.printName();
    A a;
    a.printName();
}

Однако имя определяется реализацией. Возможный вывод:

1C
1A

И вы не можете получить typeid динамического типа объекта из void*. См. этот несколько связанный вопрос: Как получить идентификатор типа пустоты * указатель?

person 463035818_is_not_a_number    schedule 29.07.2021
comment
Спасибо. Я попробовал это, и он просто вернул имя базового класса. Я включил параметр компилятора rtti, чтобы он работал так. есть ли в win32 дополнительная опция, позволяющая вернуть имя дочернего класса? - person seebee; 29.07.2021
comment
@seebee не уверен, что ты имеешь в виду. 1C это имя C - person 463035818_is_not_a_number; 29.07.2021
comment
Да, но вы сказали, что в зависимости от реализации (компилятора?!) он также может возвращать 1A (имя A). В моем случае это произошло, но это не решает проблему, так как мне нужно имя запечатанного/экземплярного класса С/1С. Я спрашиваю, внедрил ли Microsoft переключатель компилятора для управления этим поведением (Return 1A или 1C) - person seebee; 29.07.2021
comment
@seebee имена определяются реализацией для каждого класса. Т.е. вывод тоже может быть CCC AAA. Разные классы имеют разные названия - person 463035818_is_not_a_number; 29.07.2021