Какова самая простая реализация RTTI для C++?

Мой любимый визуальный инструмент слияния SourceGear DiffMerge

  • , Это свободно.
  • Межплатформенный (Windows, OS X и Linux).
  • Чистят визуальный UI
  • Все различные функции, которые Вы ожидали бы (Разность, Слияние, Разность Папки).
  • Интерфейс командной строки.
  • сочетания клавиш Usable.

User interface

8
задан freitass 4 July 2009 в 13:14
поделиться

2 ответа

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

Если класс полиморфен (имеет хотя бы одну собственную виртуальную функцию) в C ++, вероятно, в нем есть указатель на vtable, встроенный в него. Возможно, указатель vtable появляется в начале макета объекта в памяти.

Это верно для многих компиляторов, которые используют C ++ ABI - связанный вопрос SO здесь .

Если это так, вы могли получить доступ к vtable следующим образом:

void *get_vtable(void *obj)
{
    return *(reinterpret_cast<void **>(obj));
}

Затем вы можете сравнить vtables двух указателей на объекты, чтобы увидеть, указывают ли они на один и тот же тип объекта.

Итак, "переключатель типа" (что в основном и есть уловка) будет делать что-то вроде этого:

P p;
Q q;
if (get_vtable(caught) == get_vtable(&p))
{
    // it's a P...
}
else if (get_vtable(caught) == get_vtable(&q))
{
    // it's a Q...
}

Вы можете скрыть этот шаблон в макросе CATCH.

Важный момент - если вы наследуете класс из базового, но производный класс делает не переопределять какие-либо виртуальные функции и не добавлять какие-либо новые виртуальные функции, тогда компилятор предположительно может повторно использовать vtable базового класса для производного класса. Это означает, что для того, чтобы различать два типа исключений, каждый из них должен переопределять виртуальную функцию, чтобы гарантировать, что у них есть свои собственные vtables.

Обратите внимание, что это лишь малая часть того, что включает в себя обработка исключений. Также есть небольшая проблема разматывания стопки! Вам нужно вызвать деструкторы всех объектов в стеке, когда вы переходите к обработчику. Дело не только в setjmp / longjmp.

P p;
Q q;
if (get_vtable(caught) == get_vtable(&p))
{
    // it's a P...
}
else if (get_vtable(caught) == get_vtable(&q))
{
    // it's a Q...
}

Вы можете скрыть этот шаблон в макросе CATCH.

Важный момент - если вы унаследовали класс от базового, но производный класс не переопределяет какие-либо виртуальные функции и не добавляет новые виртуальные функции, тогда компилятор мог бы предположительно повторно использовать vtable базового класса для производного класса. Это означает, что для того, чтобы различать два типа исключений, каждый из них должен переопределять виртуальную функцию, чтобы гарантировать, что у них есть свои собственные vtables.

Обратите внимание, что это лишь малая часть того, что включает в себя обработка исключений. Также есть небольшая проблема разматывания стопки! Вам нужно вызвать деструкторы всех объектов в стеке, когда вы переходите к обработчику. Дело не только в setjmp / longjmp.

P p;
Q q;
if (get_vtable(caught) == get_vtable(&p))
{
    // it's a P...
}
else if (get_vtable(caught) == get_vtable(&q))
{
    // it's a Q...
}

Вы можете скрыть этот шаблон в макросе CATCH.

Важный момент - если вы унаследовали класс от базового, но производный класс не переопределяет какие-либо виртуальные функции и не добавляет новые виртуальные функции, тогда компилятор мог бы предположительно повторно использовать vtable базового класса для производного класса. Это означает, что для того, чтобы различать два типа исключений, каждый из них должен переопределять виртуальную функцию, чтобы гарантировать, что у них есть свои собственные vtables.

Обратите внимание, что это лишь малая часть того, что включает в себя обработка исключений. Также есть небольшая проблема разматывания стопки! Вам нужно вызвать деструкторы всех объектов в стеке, когда вы переходите к обработчику. Дело не только в setjmp / longjmp.

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

Обратите внимание, что это лишь малая часть того, что включает в себя обработка исключений. Также есть небольшая проблема разматывания стопки! Вам нужно вызвать деструкторы всех объектов в стеке, когда вы переходите к обработчику. Дело не только в setjmp / longjmp.

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

Обратите внимание, что это лишь малая часть того, что включает в себя обработка исключений. Также есть небольшая проблема разматывания стопки! Вам нужно вызвать деструкторы всех объектов в стеке, когда вы переходите к обработчику. Дело не только в setjmp / longjmp.

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

Обратите внимание, что это лишь малая часть того, что включает в себя обработка исключений. Также есть небольшая проблема разматывания стопки! Вам нужно вызвать деструкторы всех объектов в стеке, когда вы переходите к обработчику. Дело не только в setjmp / longjmp.

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

Обратите внимание, что это лишь малая часть того, что включает в себя обработка исключений. Также есть небольшая проблема разматывания стопки! Вам нужно вызвать деструкторы всех объектов в стеке, когда вы переходите к обработчику. Дело не только в setjmp / longjmp.

11
ответ дан 5 December 2019 в 13:01
поделиться

Простейший RTTI, который я могу придумать, - это унаследовать все классы из общей базы, которые имеют чисто виртуальную функцию GetType (). Либо заставьте его вернуть строку, либо создайте огромное перечисление со всеми типами в нем. Это довольно просто, быстро и требует небольших затрат памяти. Однако не особо гибкие.

2
ответ дан 5 December 2019 в 13:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: