C++ Can';t避免在c+中进行对象切片+;
我想构造一个C++ Can';t避免在c+中进行对象切片+;,c++,polymorphism,stdvector,object-slicing,C++,Polymorphism,Stdvector,Object Slicing,我想构造一个std::vector,其中包含从Base类派生的对象。我知道我不能直接将整个对象推入向量(对象切片的原因),所以我使用智能指针。然而,它仍然不起作用。我做错了什么 我的代码: struct Base{ int num1; explicit Base(int num1){ this->num1 = num1; } }; struct Derived : Base{ int num2; explicit Derived(
std::vector
,其中包含从Base
类派生的对象。我知道我不能直接将整个对象推入向量(对象切片的原因),所以我使用智能指针。然而,它仍然不起作用。我做错了什么
我的代码:
struct Base{
int num1;
explicit Base(int num1){
this->num1 = num1;
}
};
struct Derived : Base{
int num2;
explicit Derived(int num1, int num2) : Base(num1){
this->num2 = num2;
}
};
int main()
{
std::vector<std::unique_ptr<Base>> someList;
someList.push_back(std::make_unique<Derived>(100, 1));
someList.push_back(std::make_unique<Derived>(100, 2));
std::cout << someList[0]->num2 << std::endl; // <---- Can't access num2 !
}
结构基{
int num1;
显式基(int num1){
这->num1=num1;
}
};
派生结构:基{
int num2;
显式派生(intnum1,intnum2):基(num1){
这->num2=num2;
}
};
int main()
{
向量someList;
someList.push_back(std::make_unique(100,1));
someList.push_back(std::make_unique(100,2));
std::coutnum2派生的对象及其num2
成员都在那里,但是类型系统不知道这一点(在类似的代码中,可能不确定)
someList[0]
的类型是std::unique\u ptr
,因此->
操作符允许命名Base
的成员。一般来说,unique\u ptr
可能根本不指向派生的
,因此这是安全的方法
如果Base
类型是多态的,您可以使用dynamic\u cast
来检查对象是否确实是派生的。要使此工作正常,让我们向Base
添加一个虚拟析构函数:
struct Base{
int num1;
explicit Base(int num1){
this->num1 = num1;
}
virtual ~Base() = default;
};
然后我们可以做:
int main()
{
std::vector<std::unique_ptr<Base>> someList;
someList.push_back(std::make_unique<Derived>(100, 1));
someList.push_back(std::make_unique<Derived>(100, 2));
if (auto* dptr = dynamic_cast<Derived*>(someList[0].get()))
std::cout << dptr->num2 << std::endl;
}
intmain()
{
向量someList;
someList.push_back(std::make_unique(100,1));
someList.push_back(std::make_unique(100,2));
if(auto*dptr=dynamic_cast(someList[0].get())
std::coutnum2派生的对象及其num2
成员都在那里,但是类型系统不知道这一点(在类似的代码中,可能不确定)
someList[0]
的类型是std::unique\u ptr
,因此->
操作符允许命名Base
的成员。一般来说,unique\u ptr
可能根本不指向派生的
,因此这是安全的方法
如果Base
类型是多态的,您可以使用dynamic\u cast
来检查对象是否确实是派生的。要使此工作正常,让我们向Base
添加一个虚拟析构函数:
struct Base{
int num1;
explicit Base(int num1){
this->num1 = num1;
}
virtual ~Base() = default;
};
然后我们可以做:
int main()
{
std::vector<std::unique_ptr<Base>> someList;
someList.push_back(std::make_unique<Derived>(100, 1));
someList.push_back(std::make_unique<Derived>(100, 2));
if (auto* dptr = dynamic_cast<Derived*>(someList[0].get()))
std::cout << dptr->num2 << std::endl;
}
intmain()
{
向量someList;
someList.push_back(std::make_unique(100,1));
someList.push_back(std::make_unique(100,2));
if(auto*dptr=dynamic_cast(someList[0].get())
std::cout num2std::unique\u ptr::operator->()
允许您仅访问Base
的成员,因为返回类型是Base*
;您需要执行强制转换才能实际访问派生的
的成员。由于您仅访问派生的
的成员,向量模板参数的选择似乎有问题。也许您可以包括一些关于至少,您正试图在程序中执行。(这实际上可能是一个XY问题)您需要一个在Base
中定义并在Derived
中重写的虚拟函数。感谢您的提示,我正在尝试使用从Base
派生的元素填充std::vector
,例如,让我们调用基类Dog
,然后我可能有一个向量,其中包含Beagle
对象或BorderCo>llie
对象,但我只知道我在运行时是否在处理Border Collies的小猎犬。什么样的虚拟函数?@n.“代词是m。我对c++非常陌生。我建议在尝试使用继承之前,先阅读虚拟函数和一般的面向对象编程。这不是一个小主题和注释部分不适合解释它。std::unique\u ptr::operator->()
允许您仅访问Base
的成员,因为返回类型是Base*
;您需要执行强制转换才能实际访问派生的
的成员。由于您仅访问派生的
的成员,向量模板参数的选择似乎有问题。也许您可以包括一些关于至少,您正试图在程序中执行。(这实际上可能是一个XY问题)您需要一个在Base
中定义并在Derived
中重写的虚拟函数。感谢您的提示,我正在尝试使用从Base
派生的元素填充std::vector
,例如,让我们调用基类Dog
,然后我可能有一个向量,其中包含Beagle
对象或BorderCo>llie
对象,但我只知道我在运行时是否在处理Border Collies的小猎犬。什么样的虚拟函数?@n.“代词是m。我对c++非常陌生。我建议在尝试使用继承之前,先阅读虚拟函数和一般的面向对象编程。这不是一个小主题和注释部分不适合解释它。谢谢!在这个例子中,我将如何“在Base中使用虚拟函数”要获得相同的行为?@CharStyleаааааазаааааааааазаааа在Base
中添加一个virtual code>方法,该方法返回int
,然后让派生的重写该方法e我如何“利用Base中的虚拟函数”要获得相同的行为?@CharStyleаааааазаааааааааазаааааааазааа。