C++铸造损坏的结构
C++ casting corrupted structure
我有两个结构:
typedef struct foo
{} foo_t;
typedef struct bar : foo_t
{
int value;
} bar_t;
foo永远不应该被创建,它就像一个抽象类(我在代码中没有创建任何)。我还有一个方法,它返回一个bar,但将其返回为foo:
foo_t giveMeMyBar()
{
bar_t ret;
ret.value = 5;
return ret;
}
然后我调用该方法,并尝试将其转换为派生结构:
foo_t f = giveMeMyBar();
bar_t b = ((bar_t *) (&f));
"b"的值成员是完全错误的(一个非常大的负数)。我确信我选角错误(或者做了其他错误的事情),但我来自java,在那里选角真的很容易。
通过按值返回foo_t
,您只返回对象的foo_t
部分,类型为foo_t
-这有时被称为切片。
由于没有bar_t
对象,所以强制转换是无效的,并且使用结果指针会产生未定义的行为。
为了保留多态性,您必须返回一个指针或引用,指向函数返回后仍然存在的对象,也就是说,不指向局部变量。首先,基类将需要一个虚拟析构函数,因此可以使用指向基类的指针来安全地管理派生类:
// I'll get rid of the weird C-style typedef for readability
struct foo {
virtual ~foo() = default;
};
现在,您可以分配派生类型的对象,并返回一个指向基本类型的智能指针:
std::unique_ptr<foo> giveMeMyBar() {
auto ret = std::make_unique<bar>();
ret->value = 5;
return ret;
}
现在您可以安全地将类型投射回:
auto foo = giveMeMyBar();
bar * ptr = dynamic_cast<bar*>(foo.get()); // pointer to returned object
bar & ref = dynamic_cast<bar&>(*foo); // reference to returned object
bar copy = dynamic_cast<bar&>(*foo); // copy of returned object
如果类型错误,则指针强制转换将产生一个空指针,而引用强制转换将引发异常。
其他不太安全的铸件也可用。您使用的C样式转换是核心选项,它迫使编译器以任何可能的方式接受转换。这通常会导致未定义的行为,所以只有当你绝对确定这是你想要的时才使用它。
我来自java
那么你将不得不忘记你所学的东西。C++有一个非常不同的对象模型。
铸造真的很容易
但代价是:所有java对象都是多态的,并且都是通过托管引用间接访问的。C++允许您选择更高效但有时不太方便的值类型。
相关文章:
- 如何循环打印顶点结构
- 通过方法访问结构
- 为什么会发生堆损坏
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 使用不带参数的函数访问结构元素
- 预处理器:插入结构名称中的前一个行号
- 损坏的结构字符数组 - sqlite C++
- 在使用新操作员和C 中的结构的调用构造函数时,获得内存损坏(Malloc)
- FATFS- FIL结构会导致损坏的内存-STM32F7
- C# 封送具有 wchar_t* 成员的 C++ 结构有时会使堆损坏
- 数据结构中的双重释放或损坏
- C++铸造损坏的结构
- 由值传递的结构,在 C -> C++ 回调函数期间损坏 (gcc 4.1)
- 结构参数在函数调用时损坏
- 如何在不损坏数据的情况下将缓冲区强制转换为结构
- 文件结构,以避免数据损坏
- 结构化异常处理程序(SEH)不会捕获堆损坏
- C++ pthreads 和结构的损坏数据
- 动态结构体成员在使用 CUDA/NVCC 传递到函数时损坏
- 在OSX + llvm/libc++上内存损坏/结构重排序