对象切片是指当通过基类的引用或指针来操作派生类对象时,只会保留基类部分的情况。这通常发生在使用值传递或直接赋值操作时。
在C++中,如果有一个基类的引用或指针指向一个派生类对象,而且通过该引用或指针进行赋值或传递给函数,只有基类部分的成员被复制或传递,而派生类特有的成员将被丢失。
例如,以下代码:
class Base {
public:
int baseData;
};
class Derived : public Base {
public:
int derivedData;
};
int main() {
Derived derivedObj;
derivedObj.baseData = 10;
derivedObj.derivedData = 20;
Base baseObj = derivedObj; // 对象切片发生在这里
// 此时baseObj只包含baseData,derivedData被丢失
return 0;
}
为了避免对象切片,通常使用基类的指针或引用,并在处理多态时使用虚函数。这样可以确保在运行时调用实际类型的成员函数,而不会失去派生类的信息。
#include<iostream>
using namespace std;
class Base{
public:
virtual void print() {cout << "Base" << endl;}
};
class Derived : public Base
{
public:
virtual void print() {cout << "Derived" << endl;}
};
int main() {
// 当抛出 d 时,由于异常处理机制会进行切割(object slicing),
// 只会捕获到 Base 类型的部分。这就意味着,即使实际抛出的是 Derived 类型的对象,
// 但在 catch 块中的 Base b 只会包含 d 对象的 Base 部分。
Derived d;
try {throw d;}
catch (Base b) { b.print();} // 在这里,只有 Base 部分被复制,Derived 部分被切割
cout << "-----------------------------------------------------------------\n";
Derived d2;
try { throw &d2; }// 抛出 Derived 对象的指针
catch (Base *b) { b->print(); }// 调用的是 Derived 类中的 print() 函数
return 0;
}