首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么会发生切片?

为什么会发生切片?
EN

Stack Overflow用户
提问于 2014-10-16 21:58:36
回答 2查看 126关注 0票数 0

请考虑以下代码:

代码语言:javascript
复制
Base b;
if (something)
    b = DerivedA();
else
    b = DerivedB();

众所周知,在这种情况下,会发生‘切片’:在C++中,我们不能将基类型的变量指定为派生类型的对象;对象将从基类型中未定义的任何对象中“切片”。(如果我们想做这样的事情,我们必须使用指针或引用)。

我想了解这件事的实际原因。也就是说,Base变量不能在不切片的情况下保存Derived对象的原因。

我的假设是,这样做的原因是,Base对象和Derived对象的大小可能不一样,因此我们无法保证能够将整个Derived对象存储在Base变量中。一个Base可能占4个字节,而一个Derived占7个字节。因此,我们总是对派生对象进行切片,以适应基类型的大小。

我们可以用指针来完成这一任务,因为它们都占用了相同的内存。

这个假设正确吗?如果没有,切片的实际原因是什么?

EN

回答 2

Stack Overflow用户

发布于 2014-10-16 22:02:50

问题在于复制和移动语义(复制构造函数、复制分配等)。您正在获得这些元素的副本,但是并不是所有的元素都将被复制。如果您有一个基本指针,就不会有问题。

如果您有一个完全填充的DerivedA对象,并将其分配给本地堆栈基类型,则将使用副本赋值,而任何派生元素值都将被丢弃。

在编写副本构造函数时考虑一下。除了当前班的成员外,您还做其他的工作吗?您如何知道从当前类派生出来的内容,以及要做什么工作?试图这样做将是非常糟糕的。

代码语言:javascript
复制
class BaseType
{
private:
    int m_i;

public:
    explicit BaseType(BaseType const & other) // copy ctor
    {
        m_i = other.m_i;   // bitwise copy or memberwise copy will suffer the same issue
        // what else is there to do?  
        // BaseType has no knowledge of any other members
    }

    BaseType & BaseType::operator=(BaseType const & other)  // copy assignment
    {
        m_i = other.m_i;
        // what else is there to do?  
        // BaseType has no knowledge of any other members
    }
};

即使是按位复制(对于std::is_trivially_copyable<T>),大小也将为BaseType,正如您所指出的,比需要的要小,并且会截断数据。

希望这能有所帮助。

票数 2
EN

Stack Overflow用户

发布于 2014-10-16 22:07:08

不是的。在您的例子中,切片的原因是不同的。

Base b;行中,您为堆栈上Base类型的对象分配空间,并且已经调用了它的默认构造函数。因此,在if-statement的每个分支中,发生的是对b的赋值,它通过赋值操作符实现,通常带有签名的Base::operator=(const Base&)。如果不重载此运算符,则其默认语义为逐字段复制。注意,参数类型是Base (或const Base&),所以只有右边的Base-fields是可见的!

假设您有某种方式将DerivedA对象中包含的所有信息存储在Base对象中(尽管这不太可能),您可以将赋值操作符重载为Base::operator=(const DerivedA&),实现您自己的赋值语义,并且上面的这些都会非常好地工作。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26414622

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档