gpt4 book ai didi

c++ - 空投的运行时检查*

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:16:24 26 4
gpt4 key购买 nike

假设我有一个 void*包含指向未知 class 的指针.我想用 dynamic_cast对我实际拥有的类的类型进行运行时检查。例如:

class Foo {};

void* bar = new Foo;

如果我尝试做 dynamic_cast<Foo*>(bar)我得到:

'void *': invalid expression type for dynamic_cast

但是我需要 dynamic_cast因为在我的实际情况下我不确定 bar实际上是 Foo* .

我读过 here一个解决方案是为所有对象创建一个基类 bar可能包含 reinterpret_cast指向该基类的指针,然后尝试 dynamic_cast从该对象指针到 Foo .

这对我来说很难,因为可能存储在 bar 中的对象不都在我的掌控之中。 (因为尝试重新创建 Java 让我感到胃灼热。)还有另一种方法可以做到这一点吗?

最佳答案

dynamic_cast 用于将多态对象向下转换为一个类,该类具有您尝试转换为父对象的类型。

void* 与此完全不同。使用指向 void 的指针,您实际上是在剥离所有类型信息。

dynamic_cast 知道有一个基类,可以通过 RTTI 进行类型检查。

当你向下转换一个 void 指针时,你是在对编译器说:“是的,你知道内存中的这个地方?好吧,将它用作这种类型”,如果内存无效,则调用 UB。

你在这里有三个选择。

选项 1使用接口(interface)。好吧,多态基类是执行 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,但提供了更大的灵 active 。它使用模板为任何类型生成派生类的技巧。优点是您可以容纳任何类型,但可能会使您变得有点复杂。

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
}
}

关于c++ - 空投的运行时检查*,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33370296/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com