如何解决有没有办法将 reinterpret_cast 重新解释为虚拟派生 * 并从父级调用覆盖?
#include <iostream>
template<typename T>
struct printer {
virtual const T* get(size_t& sz) const = 0;
void print() {
size_t sz;
const T* _t = get(sz); //tries to access 'this'
for (size_t t = 0; t < sz; t++)
std::cout << _t[t] << std::endl;
}
};
template<typename T,size_t sz>
struct mask_t : public printer<T> {
T data[sz];
virtual const T* get(size_t& _sz) const override {
_sz = sz;
return data;
}
};
int main(int argc,char** argv) {
char* buffer = new char[1024];
{
using mask_f = mask_t<float,12>;
using mask_i = mask_t<int,12>;
mask_f* mf = reinterpret_cast<mask_f*>(buffer + 42);
mask_i* mi = reinterpret_cast<mask_i*>(buffer + 42);
//'this' is uninitialized
mf->print();
mi->print();
mask_f _mf = *mf;
mask_i _mi = *mi;
//ok
_mf.print();
_mi.print();
}
delete[] buffer;
return 0;
}
print()
在调用 this
时尝试访问 get()
是因为 vfptr
查找吗? 换句话说,这是不可能的吗?
编辑:我知道我可以使用 mask_t
创建一个新的 new
或者像我在这里所做的那样通过取消引用指针。然后定义了 mask_t::this
。
我不想创建实例的原因是性能问题[这在我承认的示例中不可见]。如果你想回答,请解决这篇文章中唯一的问题。
解决方法
无论类型如何,这都不是有效代码。在 C++ 中,你不能只是将一个随机指针投射到一个对象上并假装它存在。
是的,在 C++20 中,它们确实允许您在某些情况下这样做。但即便如此,这些情况也不包括对具有 virtual
成员函数的类型的操作(因为它们不够简单)。
只需使用placement-new
来构造对象。这就是应该在存储中创建对象的方式。
print() 在调用 get() 时尝试访问它是因为 vfptr 查找吗?
有关系吗?这是未定义行为如何导致崩溃的一个实现方面。
这:mask_f* mf = reinterpret_cast<mask_f*>(buffer + 42);
导致未定义的行为。就像这样:mask_f _mf = *mf;
。这两者都访问一个不存在的对象。因此,它们都表现出未定义的行为。
某个特定的编译器(版本)可能会使其中一个看起来像您想要的那样,并可能使另一个崩溃,这是一个细节和实现的问题。这两段代码同样荒谬,都不能依赖于做你想做的事。
我可以解释为什么编译器生成的程序集允许您在一种情况下使用 UB 而不是在另一种情况下。但这忽略了这样一个事实:无论哪种方式,您都依赖 UB。
我正在读取远程进程的内存。
这在 C++ 中是不合理的。无论如何,不适用于具有 virtual
成员的类型。传统的方法是将该类型的数据序列化到内存中,然后在接收过程中将其反序列化为该类型的新对象。
现在是的,如果您愿意编写特定于平台的hackery,有 方法可以像这样在进程之间传递virtual
类型。它们需要提取 vtable 指针(从有效对象中)并将它们写入从远程进程接收到的对象数据中,从而有效地原位“修复”对象。
但这些是特定于平台的黑客;如果你想要一些可移植的东西,你必须使用序列化。
,“我知道我可以通过取消引用指针来创建一个新的 mask_t
或者像我在这里所做的那样。然后定义了 mask_t::this
。”
这是错误的。当进入其构造函数的主体时,对象开始存在。 new
,包括placement new,是一种使构造函数运行的方法。其他方法只是声明一个局部或全局变量。但是,您假设的“取消引用指针”不会神奇地导致构造函数运行并创建对象。如果没有对象,this
就不能指向当前对象。
相反,您会得到未定义行为。任何事情都可能发生。您的硬盘可能会被擦除。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。