c++polymorphismsmart-pointersraw-pointer

Polymorphism : raw pointer vs smart pointer


how makes this work ?

I want to use a vector of multiple types (research, add, delete) for an inventory management (Potions, Weapons, etc.. all derived from virtual class Item).

I simplify the problem here : I have a vector containing Item (Base class) and Weapons (Derived class). For memory management issues, i prefered using unique_ptr but didn't a way to return it or use it properly.

Example Below :

// UniquePointerAndPolymorphism.cpp : Ce fichier contient la fonction 'main'. L'exécution du programme commence et se termine à cet endroit.
//

#include <iostream>
#include <vector>

class Item
{
protected:
    std::string name_;
public:
    Item(std::string name) :name_(name) {};
    virtual std::string getName() { return "b_" + name_; };
};


class Weapon : public Item
{
public:
    Weapon(std::string name) : Item(name) {};
    std::string getName() override { return "d_" + name_; };
};

std::vector<std::unique_ptr<Item>> elements;

std::unique_ptr<Weapon> getAnElement_uniquePointer(int i)
{
    /*
     *
     * How to return unique pointer from the vector ?????
     *
     */
    return std::make_unique<Weapon>("returned");

}

Weapon* getAnElement_rawPointer(int i)
{
    if (auto oneElement = dynamic_cast<Weapon*>(elements[i].get()))
    {
        return oneElement;
    }
    else
    {
        return nullptr;
    }
}


int main()
{

    elements.push_back(std::make_unique<Weapon>("1"));
    elements.push_back(std::make_unique<Item>("2"));
    elements.push_back(std::make_unique<Weapon>("3"));

    Weapon* rptElement = getAnElement_rawPointer(2);
    std::cout << rptElement->getName() << std::endl;

    std::unique_ptr<Weapon> uptElement = std::move(getAnElement_uniquePointer(0));
    std::cout << uptElement->getName() << std::endl;

}

So I have a few questions :

Thanks. Sebastien


Solution

  • A unique pointer is exactly that: unique. There is only supposed to be one unique pointer to each object. As soon as you try to return the unique pointer, there would have to be 2: one in your vector elements and one returned from your function. There are ways around this I think, like returning a reference to the pointer, but that gets messy quickly.

    You can create a shared_ptr from a unique_ptr, or you can just use a shared_ptr in your vector to begin with.

    Alternatively, in the case of an inventory system you're working with relatively simple objects. In my experience you'd want one class for the items in the actual game world, and a separate InventoryItem class for items that are stored in an inventory.

    Each item then would store the type of inventoryItem it constructs. This not only means you don't have to mess with all the ins and outs of making sure inventory items don't show up in your gameworld, it also means you can easily pass those items by value if it's more convenient, because the amount of actual data in such an item is laughably small :)

    At the end of the day it's really a personal choice how to manage your pointers, or if you should use pointers at all. Only a unique_ptr wouldn't be used according to its purpose here.