C++ 将派生类对象存储在基类变量中

C++ 将派生类对象存储在基类变量中,c++,polymorphism,object-slicing,C++,Polymorphism,Object Slicing,我想在一个向量中存储几个类的实例。由于所有类都从同一基类继承,因此这应该是可能的 想象一下这个节目: #include <iostream> #include <vector> using namespace std; class Base { public: virtual void identify () { cout << "BASE" << endl; } }; class Derived

我想在一个向量中存储几个类的实例。由于所有类都从同一基类继承,因此这应该是可能的

想象一下这个节目:

#include <iostream>
#include <vector>
using namespace std;

class Base
{
    public:
    virtual void identify ()
    {
        cout << "BASE" << endl;
    }
};

class Derived: public Base
{
    public:
    virtual void identify ()
    {
        cout << "DERIVED" << endl;
    }
};

int main ()
{
    Derived derived;

    vector<Base> vect;
    vect.push_back(derived);

    vect[0].identify();
    return 0;
}
#包括
#包括
使用名称空间std;
阶级基础
{
公众:
虚拟空标识()
{

cout你看到的是
您将派生类的对象存储在一个向量中,该向量应该存储基类的对象,这会导致对象切片,并且被存储对象的派生类特定成员被切片,因此存储在向量中的对象只是作为基类的对象

解决方案:

应将指向基类对象的指针存储在向量中:

vector<Base*> 
向量
通过存储指向基类的指针,就不会有切片,您也可以实现所需的多态行为。
由于您要求使用
C++ish
方法来实现这一点,正确的方法是使用合适的而不是在向量中存储原始指针。这将确保您不必手动管理内存,将自动为您执行此操作。

我将使用
vector
来存储它们。如果您说
矢量
,将进行切片


这意味着您必须在从向量中删除指针后自己删除实际对象,否则就可以了。

您正在经历切片。向量复制派生的对象,插入类型为
Base
的新对象。

TL;DR:您不应该从publi继承cly可复制/可移动类。


实际上,在编译时可以防止对象切片:在这种上下文中,基本对象不应该是可复制的

案例1:抽象基础

如果基础是抽象的,那么它就不能被实例化,因此您就无法体验切片

案例2:混凝土底座

如果基础不是抽象的,则可以复制(默认情况下)。您有两个选择:

  • 完全禁止复制
  • 仅允许对儿童进行复制
注意:在C++11中,移动操作会导致相同的问题

// C++ 03, prevent copy
class Base {
public:

private:
    Base(Base const&);
    void operator=(Base const&);
};

// C++ 03, allow copy only for children
class Base {
public:

protected:
    Base(Base const& other) { ... }
    Base& operator=(Base const& other) { ...; return *this; }
};

// C++ 11, prevent copy & move
class Base {
public:
    Base(Base&&) = delete;
    Base(Base const&) = delete;
    Base& operator=(Base) = delete;
};

// C++ 11, allow copy & move only for children
class Base {
public:

protected:
    Base(Base&&) = default;
    Base(Base const&) = default;
    Base& operator=(Base) = default;
};
//下面是使用vector vect的解决方案,
//Base*pBase,并用
//其地址为
//派生类型的
#包括
#包括
使用名称空间std;
阶级基础
{
公众:
虚拟空标识()
{

我想知道如果你用一个纯虚拟函数创建一个基类,然后让你的
基类和你的
派生的
继承这个基类会发生什么情况吗。@李斯特先生谢谢你的评论,但这不会改变结果。另请看。我无法让它工作。你能扩展这个测试吗ple开始工作(C++11和经典版本)不幸的是,我不能发布我迄今为止所做的事情。@ Ziga:没有它很难到达你的问题的核心;我建议你发布一个新的问题,如果你没有得到有用的答案,请毫不犹豫地回答这个评论,并指向我的问题。为什么C++ 11版本声明构造函数是公共的,不是私有的?它们是被删除的、公共的还是私有的有关系吗?@Zingam:一个被删除方法的可访问性应该一点也不重要,因此主要是将所有特殊方法分组在一起,而不是将它们分开。使用
Vector
而不是
vec。然后,使用
vec.empla而不是
vec.push_
ce_back(new-Derived())
@ShitalShah如果我想在将新派生的内容存储在向量中之前在这个新派生的内容中赋值?现在我有这样的东西:void Add(const-CThing&ins){things.push_back(ins);}
// Below is the solution by using vector<Based*> vect,
// Base *pBase , and initialized pBase with
// with the address of derived which is
// of type Derived

#include <iostream>
#include <vector>

using namespace std;

class Base
{

public:

virtual void identify ()
{
    cout << "BASE" << endl;
}
};

class Derived: public Base
{
public:
virtual void identify ()
{
    cout << "DERIVED" << endl;
}
};

int main ()

{
Base *pBase; // The pointer pBase of type " pointer to Base"
Derived derived;
// PBase is initialized with the address of derived which is
// of type Derived

pBase = & derived;
// Store pointer to object of Base class in the vector:
vector<Base*> vect;
// Add an element to vect using pBase which is initialized with the address 
// of derived
vect.push_back(pBase);
vect[0]->identify();
return 0;
}