проверьте, является ли X производным от Y через typeid

StackOverflow https://stackoverflow.com/questions/311735

  •  10-07-2019
  •  | 
  •  

Вопрос

мне нужно преобразовать указатели в long (SendMessage()) и я хочу безопасно проверить, правильна ли переменная с другой стороны.Итак, я подумывал о том, чтобы сделать dynamic_cast, но это не будет работать с классами, которые не являются виртуальными.Затем я подумал о том, чтобы сделать typeid, но это будет работать до тех пор, пока я не передам производный var в качестве его базы.

Есть ли какой-нибудь способ проверить, соответствует ли указатель тому, что я ожидаю во время выполнения?Есть ли способ, которым я могу использовать typeid, чтобы увидеть, является ли указатель типом, производным от определенной базы?

Это было полезно?

Решение

Если все, что у вас есть, это long, значит, вы мало что можете сделать. Не существует общего способа определить, представляет ли произвольное число действительный адрес памяти. И даже если вы знаете, что это действительный адрес памяти, невозможно определить тип объекта, на который указывает указатель. Если вы не можете быть уверены в истинном типе вещи до того, как ее адрес был приведен к <=>, то вы не можете быть уверены, что будет безопасно безопасно привести <=> к тому типу, который вы планируете на приведение. это к.

Вам просто нужно поверить, что отправитель сообщения отправил вам верное значение. Лучшее, что вы можете сделать, - это принять некоторые меры предосторожности, чтобы уменьшить последствия для вашей собственной программы, когда она получает поддельное значение.

Другие советы

Ваша ссылка на SendMessage() заставляет меня звучать так, будто MS Windows - ваша платформа, а затем Правила использования указателей (Windows) рекомендуется прочитать. В нем подробно описываются функции PtrToLong и PtrToUlong, а также другие функции, которые Microsoft предоставляет вам в подобных ситуациях.

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

Что вам нужно сделать, это обернуть ваше SendMessage и код, который обрабатывает сообщение, в единый безопасный интерфейс. Таким образом, вы не сможете передавать неожиданные вещи в SendMessage и не будете нуждаться в каких-либо проверках на принимающей стороне.

Система типов C ++ работает во время компиляции. Как только вы приведете указатель на long, вы потеряете всю информацию о типе. Лонг - это просто бит в памяти; нет способа определить, что он указывает на объект.

PTLib ( http://sourceforge.net/projects/opalvoip/ ) использует PCLASSINFO макрос для определения отношений между классами. Это обеспечивает такие функции, как IsDescendant и GetClass.

Возможно, вы могли бы реализовать нечто подобное.

dynamic_cast работает путем проверки подписи таблицы виртуальных методов. Если у вас нет виртуальных методов, у вас нет VMT, так что, как вы говорите, dynamic_cast не будет работать. Однако, если у вас нет VMT, вы абсолютно не знаете об объекте, на который указывает.

Лучше всего, чтобы указатели указывали на классы хотя бы с одним виртуальным методом, даже если он фиктивный. Динамическое приведение будет работать тогда.

Я пока не понимаю, о чем ваш вопрос.

  • Если вопрос в том, можете ли вы быть уверены, что приведение к long и обратно даст одинаковое значение, просмотрите Безопасная проверка типа переменной
    Учитывая "Правила использования указателей" MS-Сайта, на который ссылается другой ответчик, правильным типом для приведения является UINT_PTR.Так ты и делаешь UINT_PTR v = reinterpret_cast<UINT_PTR>(ptr); чтобы привести к целочисленному типу, и сделайте обратное, чтобы снова привести его к указателю.Стандарт C ++ гарантирует, что исходное значение будет восстановлено.(смотрите ссылку, которую я дал выше для моего объяснения этого).Кстати, на этом сайте Microsoft также говорится, что WPARAM и LPARAM меняют свой размер в зависимости от платформы.Таким образом, вы могли бы просто использовать эту переменную v и SendMessage IT.
  • Если это способ, которым вы можете проверить с другой стороны, указывает ли указатель (преобразованный в некоторый тип указателя) на какой-либо объект, ответ таков ты не можешь.Поскольку вы, по-видимому, не уверены, какой тип указателя использовался для его отправки, вы не можете проверить на принимающей стороне, на какой динамический тип указывает указатель.Если вы знаете тип, который был у указателя на стороне отправителя, ваша проверка вообще не потребовалась бы.

В Windows MFC предоставляет метод для проверки того, что данный указатель указывает на правильное расположение в памяти (это делается путем перехвата сегфоута). Я не помню название функции, но оно есть. Тем не менее, это не гарантирует, что содержимое памяти, на которую указывает, является действительным. Это может все еще иметь недопустимый VMT и вывести из строя ваш код. Конечно, вы можете перехватить segfault самостоятельно ( см. MS Knowledge База )

Что касается проверки того, принадлежит ли что-то типу, у вас должен быть базовый класс для начала. Если вы создадите деструктор базового класса & Quot; virtual & Quot; все производные классы будут иметь VMT.

Если вам нужно избегать VMT любой ценой, у вас должен быть какой-то дескриптор, который сообщает вам, с чем вы имеете дело, например, тип события в событиях MS Windows.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top