What's the preferred C++ idiom to own a collection of polymorphic objects?

后端 未结 4 795
囚心锁ツ
囚心锁ツ 2021-02-02 13:58

Consider the following classes

class Base {
public:
    virtual void do_stuff() = 0;
};

class Derived : public Base {
public
    virtual void do_stuff() { std::         


        
相关标签:
4条回答
  • 2021-02-02 14:03

    Assuming from your context that Owner is the sole owner of the contained objects,T should be unique_ptr<Base> (where unique_ptr comes from boost or std depending on your C++11 availability). This properly recognizes that it's solely owned by the container and additionally shows the ownership transferral semantics in your add_item call.

    0 讨论(0)
  • 2021-02-02 14:06

    Polymorphic objects have to be handled by pointer or reference. Since their lifetime is probably not bound to a particular scope they will also probably have dynamic storage duration, which means you should use a smart pointer.

    Smart pointers such as std::shared_ptr and std::unique_ptr work just fine in the standard collection types.

    std::vector<std::unique_ptr<Base>>
    

    Using this in Owner looks like:

    class Owner {
    public:
        void do_all_stuff() {
            //iterate through all items and call do_stuff() on them
        }
    
        void add_item(std::unique_ptr<Base> item) {
            items.push_back(std::move(item));
        }
    
        vector<std::unique_ptr<Base>> items;
    }
    

    The argument type to add_item identifies the ownership policy required for adding an item, and requires the user to go out of their way to screw it up. For example they can't accidentally pass a raw pointer with some implicit, incompatible ownership semantics because unique_ptr has an explicit constructor.

    unique_ptr will also take care of deleting the objects owned by Owner. Although you do need to ensure that Base has a virtual destructor. With your current definition you will get undefined behavior. Polymorphic objects should pretty much always have a virtual destructor.

    0 讨论(0)
  • 2021-02-02 14:12

    Other alternatives worth considering are to use boost::ptr_container, or even better, use a library like adobe::poly or boost::type_erasure for your polymorphic types, to exploit value-based run-time polymorphism—avoids the need for pointers, inheritance, etc.

    0 讨论(0)
  • 2021-02-02 14:12

    Actually you cannot store references in STL, only pointers or real values. So T is Base* Try other things you will have your compiler complaining.

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