Как получить typeid указателя void*?
У меня есть список указателей на объекты. Эти объекты не имеют ничего общего (т.е. не имеют общего базового класса); для лучшего понимания: это список объектов, которые находятся под курсором мыши в графическом интерфейсе.
Теперь я хотел бы знать, что это за объект. Узел, дескриптор узла, линейный сегмент, тег и т. Д. Однако я не могу использовать typeid(*ptr)
поскольку птр является const void*
,
Любое решение для этого? Можно ли принудительно использовать typeid, поскольку я знаю, что указатели всегда указывают на объекты, а не на простые значения? Или нет никакого способа добавить какой-нибудь поддельный общий базовый класс?
(edit: В настоящее время я делаю это таким образом, чтобы сохранить структуру в списке, которая дополнительно хранит тип объекта (как enum). Может быть, я должен изменить это, чтобы сохранить type_info
объект...)
4 ответа
Для технического решения, не учитывая уровень дизайна, используйте std::map
или хеш-таблицу (как угодно), чтобы связать нетипизированные указатели с дескрипторами типов или типизированными указателями, конечно, до того, как пользователь начнет использовать мышь.
На более высоком уровне указатели void* просто плохие.
Было бы лучше, чтобы исправить дизайн, а не использовать Kludge, как std::map
,
Ура & hth.
Вы определенно должны ввести базовый класс полиморфных пустышек или для этой цели. В противном случае вам нужно будет сделать reinterpret_cast/static_cast
сначала к другому, возможно, не связанному типу указателя, чтобы иметь возможность вызывать dynamic_cast
, Поскольку доступ к объекту с неправильным типом в C++ не определен, такое использование dynamic_cast
вызовет неопределенное поведение.
Технически информация RTTI обычно хранится в поле vtable объекта, поэтому перехват двоичного представления может просто сработать и дать вам уникальный указатель для каждого типа. Пожалуйста, не делай этого.
Вам следует рассмотреть возможность использования типа boost::variable для хранения ваших необработанных указателей (перед тем, как преобразовать их в void*), и вместо этого сохранить их в своем списке.
Затем вы можете либо попытаться получить свои указатели обратно напрямую, используя функцию-член Get, или еще лучше, если у вас есть несколько возможных типов для работы в одной точке, используя синтаксис посетителя.
Объявите и определите новый класс с именем "Object":
class Object
{
private: const void *pointer
const char *type;
public: template <class T> Object(const T *t)
{
this->pointer = t;
this->type = typeid(*t).name();
//NOTE that you must #include <typeinfo.h> in order to use the "typeid" keyword of course!
}
const void* GetPointer()
{
return this->pointer;
}
const char* GetType()
{
return this->type;
}
template <class T> const T* GetPointer()
{
return (T*)this->pointer;
}
template <class T> T& GetReference()
{
return *(T*)this->pointer;
}
template <class T> T GetValue()
{
return *(T*)this->pointer;
}
//You also can add some explicit and/or implicit conversions operators if you want by using template class in each
};
Затем замените ваш void*
с Object
в вашем списке.
Каждый раз, когда вы повторяете этот список, сначала вызывайте GetType
функция Object
класс, чтобы узнать тип объекта, который указатель void этого Object
указывает на. GetType
возвращает имя этого типа как const char*
строка.
Вы можете использовать strcmp
функция, чтобы помочь вам сравнить const char*
строки.
Затем после этого вы позвонили GetType
функция, теперь вы знаете, к какому типу конвертировать или приводить пустой указатель Object
а затем делайте что хотите с текущим повторяющимся объектом!
Вызовите одну из двух перегрузок GetPointer
функция для получения пустого указателя Object
преобразован / отлит или нет.
Если вы просто хотите ссылку на объект, указатель void Object
указывает на, затем просто позвоните GetReference
вместо этого GetPointer
,
Надеюсь, вам понравится мой ответ!