3

如何使这项工作?

我想使用多种类型的向量(研究、添加、删除)进行库存管理(药水、武器等。所有这些都派生自虚拟类 Item)。

我在这里简化了问题:我有一个包含项目(基类)和武器(派生类)的向量。对于内存管理问题,我更喜欢使用 unique_ptr 但没有办法返回或正确使用它。

下面的例子:

// 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;

}

所以我有几个问题:

  • 即使看起来不是问题,多态性是否与智能指针兼容?
  • 返回原始指针是唯一的解决方案吗?
  • 我是否必须使用 shared_pointer 在向量和程序的另一部分中使用它?
  • 有没有办法返回参考?

谢谢。塞巴斯蒂安

4

2 回答 2

1

即使看起来不是问题,多态性是否与智能指针兼容?

是的,多态性与智能指针兼容。

返回原始指针是唯一的解决方案吗?

不,返回原始指针不是唯一的解决方案。(请参阅下面的可选参考答案。)

一种约定是使用原始指针来指示非拥有指针

不幸的是,通常不清楚原始指针是否是非拥有指针的意图,因为历史上原始指针通常是拥有指针。

如果您采用这样的策略,您将需要遵守原始指针是非拥有指针的规则。(我认为这是一个很好的政策,我使用它。)

我是否必须使用 shared_pointer 在向量和程序的另一部分中使用它?

不,您不必使用shared_ptr。使用 shared_ptr 是联合所有权。

联合所有权相当于是一个全局变量。除非对象是不可变的,否则对对象状态的推理是很棘手的,尤其是当不同的所有者有不同的不变量时。

我考虑使用 shared_ptr 作为最后的手段。我去智能指针是一个 unique_ptr (和原始指针作为非拥有)。

有没有办法返回参考?

是的,您可以返回对武器的引用。

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

    throw std::logic_error("No weapon");
}

但是如果索引引用的对象不是武器怎么办?代码需要抛出异常。

抛出异常的另一种方法是返回 a ,当该索引处没有 Weapon 时,std::optional<std::reference_wrapper<Weapon>>它可能是 a 。std::nullopt_t然后调用者需要显式访问可选。

如果调用者忽略检查,这也比原始指针更安全nullptr,这是一个容易犯的错误,编译器不会帮助捕捉这些错误。

于 2021-10-16T12:56:57.437 回答
0

唯一的指针就是:唯一的。每个对象只应该有一个唯一的指针。一旦您尝试返回唯一指针,就必须有 2 个:一个在您的向量元素中,一个从您的函数返回。我认为有一些方法可以解决这个问题,比如返回对指针的引用,但这很快就会变得混乱。

您可以从 unique_ptr 创建一个 shared_ptr,或者您可以只在向量中使用 shared_ptr 开始。

或者,在库存系统的情况下,您正在使用相对简单的对象。根据我的经验,您需要一个用于实际游戏世界中的项目的类,以及一个用于存储在库存中的项目的单独的 InventoryItem 类。

然后每个项目将存储它构造的inventoryItem 的类型。这不仅意味着您不必为确保库存物品不会出现在您的游戏世界中而搞砸所有的来龙去脉,还意味着如果更方便的话,您可以轻松地按价值传递这些物品,因为数量这样一个项目中的实际数据小得可笑:)

归根结底,如何管理指针,或者是否应该使用指针,真的是个人选择。根据此处的目的,只有 unique_ptr 不会被使用。

于 2021-10-16T12:51:21.050 回答