C++ 将派生类的指针插入基类的向量时的切片

C++ 将派生类的指针插入基类的向量时的切片,c++,object-slicing,C++,Object Slicing,我的基类名为Account,而派生类Businessaccount有一个名为x的额外int变量,以及一个getter方法(int getx())。 切片是否应该在以下情况下发生?这显然发生在我的情况中: vector<shared_ptr<Account>> vec; shared_ptr<Businessaccount> sptr = make_shared<Businessaccount>(); vec.push_back(sptr); 它

我的基类名为
Account
,而派生类
Businessaccount
有一个名为
x
的额外
int
变量,以及一个getter方法(
int getx()
)。 切片是否应该在以下情况下发生?这显然发生在我的情况中:

vector<shared_ptr<Account>> vec;
shared_ptr<Businessaccount> sptr = make_shared<Businessaccount>();

vec.push_back(sptr);
它说
没有名为
getx()的成员

如果有人能告诉我发生这种情况的原因以及如何解决,我将不胜感激。

(*vec.at(0))
将返回一个不知道
x
帐户。您需要将
Account
指针强制转换为
Businessaccount
以引用该成员

shared_ptr<BusinessAccount> bA = dynamic_pointer_cast<BusinessAccount>(vec.at(0));
bA->getx();
shared_ptr bA=dynamic_pointer_cast(向量位于(0));
bA->getx();

不,在这种情况下不会发生切片,您的指针只是转换为指向基类的指针,即您的数据是相同的,只是更改了指针的类型。当发生切片时,会丢失派生类的所有数据


要解决此问题,您需要在基类中提供虚拟方法,该方法将在
Businessaccount
中正确实现,或者使用
dynamic\u cast
static\u cast
(如果您确定对象的类型是
Businessaccount
)。虽然使用这种CAST通常是设计不好的程序的标志,但是C++中的“/P>>P>”,指向的对象的静态和动态类型可以不同。 该vec中共享指针指向的静态类型是
帐户

该vec中共享指针指向的动态类型各不相同。在您的案例中,您在其中放置了一个
Businessaccount

当您想要访问或调用方法时,您只能访问静态类型的方法

静态类型是您已经向编译器证明该类型在该行中包含的类型

如果您知道得更清楚,可以执行
静态转换(vec.at(0).get())->getx()
。通过这样做,您可以向编译器保证,您知道该位置的数据实际上是一个
Businessaccount
。如果你错了,你的程序的行为是未定义的(如果你很幸运你得到了崩溃)

您还可以使用RTTI(运行时类型信息)询问特定对象是否为特定子类型(在某些情况下,基类具有虚拟方法)

Account*paccount=vec.at(0.get();
Businessaccount*pba=动态广播(paccount);
如果(pba)
pba->getx();
上面检查
paccount
是否实际上是
Businessaccount*
,如果是,则对其调用
getx
。如果没有,它什么也做不了

通常情况下,动态投射是一种迹象,表明您没有正确地设计和使用对象;必须深入了解接口,这意味着您的接口可能不够丰富

在一些脚本语言和字节码编译语言中,如果没有该方法,它们允许您关闭并调用
getx
,然后继续崩溃/抛出异常/etc


相反,C++允许您使用您声称存在的内容(通过类型系统),然后允许您在需要动态类型检查时编写自己的处理程序。

这不是切片,但编译器当然正确地认为指针从
at()返回
不能直接用于访问派生类的成员函数
帐户是否有名为
getx()
的成员?通过指针调用方法的典型方式是
->
运算符<代码>向量at(0)->getx()@FatihBAKIR
shared_ptr<BusinessAccount> bA = dynamic_pointer_cast<BusinessAccount>(vec.at(0));
bA->getx();
Account* paccount = vec.at(0).get();
Businessaccount* pba = dynamic_cast<Businessaccount*>(paccount);
if (pba)
  pba->getx();