【问题标题】:How does C++ object slicing work internally? [duplicate]C++ 对象切片如何在内部工作? [复制]
【发布时间】:2020-03-03 10:00:26
【问题描述】:

对象切片在 C++ 中是如何工作的?

有人可以帮我理解对象切片是如何工作的吗?具体来说,我有 Class3 类,它公开继承 Class1 和 Class2 类,如下所示

class Class1 
{
    int a, b;
public:
    Class1() : a(11), b(12){}
    void get(){cout<<"\nget from Class1: this:"<<this;}
};

class Class2 
{
    int c, d;
public:
    Class2() : c(13), d(14){}
    void get(){cout<<"\nget from Class2: this:"<<this;}
};

class Class3 : public Class1, public Class2
{
public: 
    Class3(): Class1(), Class2(){};
    void get(){cout<<"\nget from Class3: this:"<<this;}
};

int main()
{
    Class3 obj;
    Class1& c1ref = obj;
    Class2& c2ref = obj;
    c1ref.get();
    c2ref.get();
    return 0;
}

输出:

get from Class1: this:0x70d12c86dd30
get from Class2: this:0x70d12c86dd38

我的理解是当我们将 c1ref/c2ref 分配给 obj 时,它必须在内部进行一些计算,然后才能将值分配给 c1ref/c2ref。这些值是如何计算出来的?

【问题讨论】:

标签: c++ object-slicing


【解决方案1】:

您的示例本身不包括 对象切片

在您的示例中,Class3Class1Class2 组成。当您读取指针时,您会得到指向 子对象 的指针(为了更好地理解这一点,您可以考虑如果它们是成员变量而不是继承,这将是类似的)。


当您将子类分配给基类类型时会发生对象切片(指针和引用不会发生)。在您的示例中,这相当于:

Class1 c1 = c3;//slicing occurs (that is, you created a brand new object of type Class1)

【讨论】:

  • Class1由Class2和Class3组成,有意思吗?
【解决方案2】:

这里没有对象切片。让我们看看你的代码实际上做了什么:

Class3 obj;

好的,obj 是一个 Class3 对象。由于它继承自 Class2,因此 implementation(*) 在其中存储了一个 Class2 对象。

Class2& c2ref = obj;

您已为obj 创建了一个引用。所以没有发生切片。简单的c2ref地址就是obj中包含的Class2子对象的地址(这只是一个实现细节)。

Class3& c3ref = obj;

c3ref 只是对obj 的引用。

c2ref.get();

由于get 不是虚拟的,因此您在obj 上调用Class2 版本。

c3ref.get();

你在obj上调用Class3版本

要实际切片对象,您应该使用分配或复制到 Class2 对象:

Class2 c2 = obj;

这是正确的,因为obj 通过继承Class2 对象,但c2 现在只包含来自objClass2 成员并且丢失了Class1 部分以及具体的Class3 部分。


(*) C++ 标准没有指定实现处理继承的方式。但是通过子对象实现是常用的,所以我假设你的实现是这样的。

【讨论】:

    猜你喜欢
    • 2011-05-07
    • 2013-08-19
    • 1970-01-01
    • 1970-01-01
    • 2020-05-07
    • 2020-06-21
    • 2020-01-31
    • 2011-04-24
    • 2013-05-11
    相关资源
    最近更新 更多