【问题标题】:Base and derived objects held in vector of base class type get sliced在基类类型的向量中保存的基对象和派生对象被切片
【发布时间】:2021-09-05 01:36:37
【问题描述】:

所以我刚刚学习了矢量模板的基础知识,我正在尝试制作一个同时包含 Base 对象和 Derived 对象类的矢量。但是派生对象会被切片(仅打印 baseVariable,尽管它也应该打印 DerivedVariable。所以我有两个问题,首先: 是否在此处正确完成了使用用户输入创建新对象?我可以让它更好或更短吗?

Base* ptr = new Base();
            cin >> *ptr;
            vec.push_back(unique_ptr<Base>(ptr));

为什么派生对象会被切片?

class Base
{
protected:
    string baseVariable_;
public:
    void display() {
        cout << "BaseVar: " << baseVariable_ << endl;
    }
    friend istream& operator>>(istream& in, Base& obj);

};
istream& operator>>(istream& in, Base& obj)
{
    in >> obj.baseVariable_;
    return in;
}



class Derived :public Base
{
public: //public just for test
    string derivedVariable_;
    void display() {
        Base::display();
        cout << "DerivedVar: " << derivedVariable_ << endl;
    }
    friend istream& operator>>(istream& in, Derived& obj);
};
istream& operator>>(istream& in, Derived& obj)
{
    in >> obj.baseVariable_>> obj.derivedVariable_;
    return in;
}
int main()
{
    unsigned int choice = 0;
    vector<unique_ptr<Base>>vec;
    while (true)
    {
        cout << endl << "1. Add object of base class" << endl;
        cout << endl << "2. Add object of derived class" << endl;
        cout << endl << "3. Display all added objects to vector";
        cout << endl << "Choose option: ";
        cin >> choice;
        switch (choice)
        {
        case 1:
        {
            Base* ptr = new Base();
            cin >> *ptr;
            vec.push_back(unique_ptr<Base>(ptr));
            
            break;
        }
        case 2:
        {
            Derived* ptr = new Derived();
            cin >> *ptr;
            vec.push_back(unique_ptr<Base>(ptr));
            //delete ptr; <- it can't be here.
            break;
        }
        case 3:
            cout << "Displaying...\n";
            for (size_t i = 0; i < vec.size(); i++)
            {
                vec[i]->display();
            }
            cout << "---------------------\n";
            break;

        }
    }
}

【问题讨论】:

  • Derived 对象将在 vec 销毁时被切片,因为 Base 析构函数不是 virtual
  • 请阅读minimal reproducible example。您的代码缺少包含,更重要的是缺少示例输入、输出和预期输出。我冒着风险写了一个答案,但我无法确定它是否能解决你的问题,因为我无法找到有意义的输入,而且我不知道什么是错误/正确的输出
  • 确实有帮助,谢谢。

标签: c++ vector derived-class


【解决方案1】:

您的代码中没有切片。您忘记将Base::display 声明为虚拟,因此在Base* 上调用display 将调用Base::display

class Base
{
protected:
    string baseVariable_;
public:
    virtual void display() {
    // ^^----------------------------------------------- !!!
        cout << "BaseVar: " << baseVariable_ << endl;
    }
    friend istream& operator>>(istream& in, Base& obj);
    virtual ~Base() {}
};

对于多态类型,您还需要添加一个虚拟析构函数。

【讨论】:

  • 你在这个特定的代码中是对的,添加 virtual 解决了这个问题。我的主程序中有虚拟显示方法,但它也不起作用。我通过重写矢量/对象创建来解决这个问题。谢谢!
  • @RektLeft 查看我对您问题的评论。如果没有virtual,它就无法按您期望的方式工作。您的代码中可能有更多错误
  • 我知道如果我想编辑派生类的方法,'virtual' 是必须的,但我忘了它。
  • @RektLeft 是的,没关系,但是当它不能解决问题时,你不应该接受这个答案。 “重写向量/对象创建”是什么意思?
  • 但它确实修复了上面的代码,所以它必须是一个可接受的答案。我的意思是来自线程的代码。 What do you mean by "rewriting vector/object creation"? 从字面上看,只是删除了所有内容并从头开始。
猜你喜欢
  • 2018-09-17
  • 2013-03-27
  • 1970-01-01
  • 2014-02-02
  • 1970-01-01
  • 2014-06-16
  • 2012-02-05
相关资源
最近更新 更多