在c++中,什么是对象切片,什么时候发生?


当前回答

当派生类对象分配给基类对象时,派生类对象的所有成员都将复制到基类对象,但基类中不存在的成员除外。这些成员被编译器切片。这称为对象切片。

下面是一个示例:

#include<bits/stdc++.h>
using namespace std;
class Base
{
    public:
        int a;
        int b;
        int c;
        Base()
        {
            a=10;
            b=20;
            c=30;
        }
};
class Derived : public Base
{
    public:
        int d;
        int e;
        Derived()
        {
            d=40;
            e=50;
        }
};
int main()
{
    Derived d;
    cout<<d.a<<"\n";
    cout<<d.b<<"\n";
    cout<<d.c<<"\n";
    cout<<d.d<<"\n";
    cout<<d.e<<"\n";


    Base b = d;
    cout<<b.a<<"\n";
    cout<<b.b<<"\n";
    cout<<b.c<<"\n";
    cout<<b.d<<"\n";
    cout<<b.e<<"\n";
    return 0;
}

它将产生:

[Error] 'class Base' has no member named 'd'
[Error] 'class Base' has no member named 'e'

其他回答

当派生类对象被分配给基类对象时,派生类对象的其他属性将从基类对象中切下(丢弃)。

class Base { 
int x;
 };

class Derived : public Base { 
 int z; 
 };

 int main() 
{
Derived d;
Base b = d; // Object Slicing,  z of d is sliced off
}

C++中的切片问题源于其对象的值语义,这主要是由于与C结构的兼容性。您需要使用显式引用或指针语法来实现大多数其他语言中的“正常”对象行为,即对象总是通过引用传递。

简单的答案是,通过按值将派生对象分配给基础对象来切片对象,即,剩余对象只是派生对象的一部分。为了保持值语义,切片是一种合理的行为,其用途相对较少,这在大多数其他语言中都不存在。有些人认为它是C++的一个特性,而许多人则认为这是C++的怪癖/错误特性之一。

在我看来,除了你自己的类和程序架构/设计不好之外,切片并不是什么问题。

如果我将一个子类对象作为参数传递给一个方法,该方法接受一个超类类型的参数,那么我当然应该意识到这一点,并且知道在内部,被调用的方法只能使用超类(也称为基类)对象。

在我看来,提供一个请求基类的子类会导致子类特定的结果,这似乎只是一个不合理的期望,会导致切片成为一个问题。它要么在方法的使用上设计糟糕,要么子类实现糟糕。我猜这通常是牺牲了良好的OOP设计,而为了方便或提高性能的结果。

在C++中,派生类对象可以分配给基类对象,但另一种方式是不可能的。

class Base { int x, y; };

class Derived : public Base { int z, w; };

int main() 
{
    Derived d;
    Base b = d; // Object Slicing,  z and w of d are sliced off
}

当派生类对象分配给基类对象时,对象切片发生,派生类对象的其他属性被切片以形成基类对象。

当派生类对象分配给基类对象时,派生类对象的所有成员都将复制到基类对象,但基类中不存在的成员除外。这些成员被编译器切片。这称为对象切片。

下面是一个示例:

#include<bits/stdc++.h>
using namespace std;
class Base
{
    public:
        int a;
        int b;
        int c;
        Base()
        {
            a=10;
            b=20;
            c=30;
        }
};
class Derived : public Base
{
    public:
        int d;
        int e;
        Derived()
        {
            d=40;
            e=50;
        }
};
int main()
{
    Derived d;
    cout<<d.a<<"\n";
    cout<<d.b<<"\n";
    cout<<d.c<<"\n";
    cout<<d.d<<"\n";
    cout<<d.e<<"\n";


    Base b = d;
    cout<<b.a<<"\n";
    cout<<b.b<<"\n";
    cout<<b.c<<"\n";
    cout<<b.d<<"\n";
    cout<<b.e<<"\n";
    return 0;
}

它将产生:

[Error] 'class Base' has no member named 'd'
[Error] 'class Base' has no member named 'e'