当放置在容器中时,C++子类型退化

C++ subtype degeneration when placed in a container

本文关键字:C++ 类型      更新时间:2023-10-16

我目前正在学习一门来自java背景的c++课程。

我们现在已经到了讨论继承的地步。这周的课并没有真正解释每周作业需要做什么,这让我在试图解决这些问题时有些不知所措。

虽然我会抽出时间问我的导师,但这意味着要等到下周,让我落后。

请允许我展示我想做的事情:

class base
{
   int field1;
   base(int _field): 
   field1(_field){}
};
class subclass : public base
{
   int field2;
   public:
   subclass(int _field2):
      base(_field1),field2(_field2){}

   string to_string()
   {
       return "I am a subtype!!";
   }
};
int main()
{
    vector<base> x;
    x.push_back(subclass(123,456));
    cout<<x[0].to_string[]<<end; //error!!
}

令我惊讶的是,这段代码无法工作,甚至无法编译。容器x将把其中的对象强制转换为基类型,这意味着我被迫将曾经的子类型视为基类型。这意味着子类型变量和函数遥不可及。

我想做的是将容器中的对象视为子类型,IE对它们进行类型测试(这本身就是一件小事),然后根据对象的类型做不同的事情。

这在java中是微不足道的。在那里,我可以简单地用子类型填充一个类型库数组,然后对其中的对象执行我想要的任何操作。

我假设我在java中所做的,在C++中应该是可能的,能够将子类型放入某种容器中,然后将它们视为应该可能的子类型。很明显,我在这里误解了一些基本的东西,这个问题对我来说是完全不可预见的

值得一提的是,我在向量和简单数组中都尝试过这种方法。出现了完全相同的模式,数组的类型决定了我如何访问对象,即我不能调用to_string()。

总结一下:我想知道如何在容器中包含子类型,而不让容器将内部的对象强制转换为容器的类型。

这在Java中是微不足道的。在那里,我可以简单地用子类型填充一个类型库数组,然后对其中的对象执行我想要的任何操作。

Java和C++中对象的主要区别在于,所有Java对象都是通过引用访问的(有点类似于C++智能指针),而在C++中,您可以选择直接访问对象。这可以很好地工作,并使用非多态对象节省大量内存和一些CPU周期,但由于对象切片,一旦继承进入阶段,就会显著中断。

把十磅的东西放进一个五磅的袋子是个问题:vector<base>分配了足够的空间来容纳base类型的N项目,所以当你试图把subclass放进同一个空间时,编译器告诉你它不适合。

要解决这个问题,请模仿Java的做法,即使用智能指针:

vector<unique_ptr<base> > x;
unique_ptr<base> item(new subclass(123,456));
x.push_back(std::move(item));

演示。

注意:您的代码中有几个问题需要修复才能正常工作。首先,向base添加一个公共to_string成员函数。然后,将通过点.运算符对to_string的调用替换为通过箭头->运算符的调用。最后,修复一些拼写错误——to_string调用中的方括号,以及endl中缺少的l