dynamic_cast
является использование повергнуть полиморфный объект класса, который имеет тип объекта, который вы пытаетесь бросить, как это родитель.
void*
полностью отличается от этого. с указателем на пустоту, вы буквально лишаете информацию каждого типа.
dynamic_cast
Знайте, что существует базовый класс и вы можете проверить тип через RTTI.
Когда вы отбрасываете указатель на пустоту, вы говорите компилятору: «Да, вы знаете это место в памяти? Ну, используйте его как этот тип», и если память недействительна, вызывается UB.
у вас есть три варианта.
Вариант 1 Используйте интерфейс. Ну, полиморфный базовый класс - единственный способ сделать dynamic_cast
. Другого пути нет, никаких хаков, это единственный способ. Просто как тот.
struct Base { virtual ~Base() = default; };
struct Derived : Base {};
// ...
void test (Base* base) {
auto derived = dynamic_cast<Derived*>(base);
if (derived) {
// derived is valid here.
}
}
Вариант 2 Определить тип с указателем я использую метод, чтобы иметь уникальный идентификатор каждого типа и использовать идентификатор, чтобы подтвердить бросок. Совершено без RTTI
using type_id_t = void(*)();
template <typename T> void type_id() {}
// now we can use a map or a vector.
std::vector<std::pair<type_id_t, void*>> vec;
template<typename T>
void insertToMyVector(T* obj) {
vec.emplace_back(type_id<T>, obj);
}
template<typename T>
T* getObj(int index) {
auto item = vec[index];
return static_cast<T*>(item.first == &type_id<T> ? item.second : nullptr);
}
// ...
int main() {
auto foo = new Foo;
insertToMyVector(foo);
auto maybeFoo = getObj<Foo>(0);
if (maybeFoo) {
// you have a valid Foo here
}
}
Вариант 3 Сформировать производный класс для любого типа Это один весьма полезным, поскольку оно может содержать любой тип, сохраняя безопасность типов. Я выгляжу как решение 1, но предлагаю большую гибкость. Хитрость это для создания производного класса для любого типа с использованием шаблонов. Преимущество состоит в том, что вы можете держать любой тип, но можете немного усложнить вам немного.
struct Base { virtual ~Base() = default; };
template<typename T>
struct Derived : Base {
Derived(T&& obj) : _obj{std::move(obj)} {}
Derived(const T& obj) : _obj{obj} {}
T& get() {
return _obj;
}
const T& get() const {
return _obj;
}
private:
T _obj;
};
// ...
void test (Base* base) {
auto derived = dynamic_cast<Derived<int>*>(base);
if (derived) {
int i = derived->get();
// derived is valid here, and we can safely access the int
}
}
Вы не можете ... –
Тогда вам понадобится дополнительное состояние, чтобы рассказать вам, какой он тип. –
Создайте интерфейс/абстрактный класс и объявите панель этого типа. –