Store derived class objects in base class variables

前端 未结 5 885
一生所求
一生所求 2020-11-22 16:18

I would like to store instances of several classes in a vector. Since all classes inherit from the same base class this should be possible.

Imagine this program:

相关标签:
5条回答
  • 2020-11-22 16:51
    // 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;
    }
    
    0 讨论(0)
  • 2020-11-22 16:53

    TL;DR: You should not inherit from a publicly copyable/movable class.


    It is actually possible to prevent object slicing, at compilation time: the base object should not be copyable in this context.

    Case 1: an abstract base

    If the base is abstract, then it cannot be instantiated and thus you cannot experience slicing.

    Case 2: a concrete base

    If the base is not abstract, then it can be copied (by default). You have two choices:

    • prevent copy altogether
    • allow copy only for children

    Note: in C++11, the move operations cause the same issue.

    // 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;
    };
    
    0 讨论(0)
  • 2020-11-22 16:56

    You're experiencing slicing. The vector copies the derived object, a new one of type Base is inserted.

    0 讨论(0)
  • 2020-11-22 16:59

    What you are seeing is Object Slicing.
    You are storing object of Derived class in an vector which is supposed to store objects of Base class, this leads to Object slicing and the derived class specific members of the object being stored get sliced off, thus the object stored in the vector just acts as object of Base class.

    Solution:

    You should store pointer to object of Base class in the vector:

    vector<Base*> 
    

    By storing a pointer to Base class there would be no slicing and you can achieve the desired polymorphic behavior as well.
    Since you ask for a C++ish way of doing this, the right approach is to use a suitable Smart pointer instead of storing a raw pointer in the vector. That will ensure you do not have to manually manage the memory, RAII will do that for you automatically.

    0 讨论(0)
  • 2020-11-22 16:59

    I'd use vector<Base*> to store them. If you say vector<Base>, slicing will occur.

    This does mean that you'd have to delete the actual objects yourself after you've removed the pointers from your vector, but otherwise you should be fine.

    0 讨论(0)
提交回复
热议问题