【问题标题】:Inheriting from standard library containers results in slicing从标准库容器继承会导致切片
【发布时间】:2020-10-09 12:22:39
【问题描述】:

我遇到了一个旧的SO post about inheriting from std::vector。我不清楚其中一个 cmets,为什么当您从标准库容器继承并使用指向基的指针/引用时会发生切片?

Godbolt

#include <vector>
#include <iostream>

using namespace std;

class MyVec : public vector<int>
{};

void printTypeBase(vector<int>& vecObj)
{
    cout << "base parameter ref: " << typeid(vecObj).name() << endl;
}

void printTypeDerived(MyVec& vecObj)
{
    cout << "derived parameter ref: " << typeid(vecObj).name() << endl;
}


int main()
{
    auto myVec = MyVec{};

    printTypeBase(myVec);
    printTypeDerived(myVec);
}

输出:

基本参数参考:St6vectorIiSaIiEE

派生参数参考:5MyVec


当我尝试在 printTypeBase 内进行动态转换时:

auto temp = dynamic_cast<MyVec&>(vecObj);

我收到一条明确的错误消息:

错误:'std::vector' 不是多态的


回想起来,我的问题应该是为什么std::vector 不是多态类型?

【问题讨论】:

  • 这里没有进行切片,因为使用了指向引用的指针。在任何地方用class foo 替换std::vector&lt;int&gt;,你会得到相同的结果。
  • C++ 中的类型不是动态的,它们是固定的和静态的。在printTypeBase 函数中,vecObj 变量是对vector&lt;int&gt; 的引用,编译器无法更改它。
  • 这不是切片。 MyVec 是一个空的派生类。里面没有什么可以切的。如果要查看切片,则添加一个数据成员,例如 int,然后通过 vector&lt;int&gt;&amp; 复制对象。然后你得到int成员的切片,因为vector&lt;int&gt;::operator=int成员一无所知。
  • @SamVarshavchik when I replace vector<int> with a foo class 其中包含虚函数,我得到“正确”行为,typeid 为这两个函数打印“MyVec”。我现在明白了关于非多态类型的意义,所以这是有道理的。
  • 即使使用虚函数,仍然不会发生切片。它仅在基类被复制 时发生。不进行复制。 typeid 并不表示对象切片正在发生。

标签: c++ inheritance containers


【解决方案1】:

标准库容器没有虚拟方法,也没有虚拟析构函数。他们完全没有 vtable。

您的代码无法测试您想要测试的内容。

【讨论】:

    【解决方案2】:

    但是,对于非多态类型的引用(例如没有虚拟方法的类),这里不会发生切片,typeid 解析为参数的静态类型信息,而不是动态类型。

    【讨论】:

      【解决方案3】:

      为什么会出现切片

      您的示例中没有切片。与从任何其他类型继承相比,标准库容器没有什么特别会导致切片。

      基本参数参考:St6vectorIiSaIiEE

      错误:'std::vector' 不是多态的

      后一个错误解释了typeid 的结果。 Vector 不是多态类型。这是因为它没有虚函数。 dynamic_cast 只允许用于多态类型,typeid 仅在引用多态类型时才解析为动态类型。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-07-09
        • 2016-08-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-07
        相关资源
        最近更新 更多