C++铸造损坏的结构

C++ casting corrupted structure

本文关键字:结构 损坏 C++      更新时间:2023-10-16

我有两个结构:

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++允许您选择更高效但有时不太方便的值类型。