c++ - 管理标准容器中的抽象类

标签 c++ c++11

经过大量研究,我仍然不明白如何使用智能指针处理抽象类集合。

这是我得到的错误:

error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Shape; _Dp = std::default_delete<Shape>]'
   base_ptr s = shapes.front();

error: no matching function for call to 'std::unique_ptr<Shape>::unique_ptr(Shape&)'
   shapes.push(base_ptr(b));

通过编译最少的代码来复制错误 (code online avaiable)。

    #include <queue>
    #include <memory>

    class Shape {
    public:
        virtual int getPerimeter() =0;
    };

    typedef std::unique_ptr<Shape> base_ptr;

    class Circle : public Shape {
    public:
        virtual int getPerimeter() { return 1; };
    };

    class Square : public Shape {
    public:
        virtual int getPerimeter() { return 0; };
    };

    class ShapeManager {
    public:
        ShapeManager();
        void useShape() {
            if(shapes.empty())
                throw "Work stack is empty.";

            base_ptr s = shapes.front();
            s->getPerimeter();
            shapes.pop();
        }

        void submitShape(Shape &b) {
            shapes.push(base_ptr(b));
        }
    private:
        std::queue<base_ptr> shapes;
    };

    int main(int argc, char **argv) {
        ShapeManager s();
        Circle c;
        s.submitShape(c);
        s.useShape();
        return 1;
    }

如果我声明 queue 就可以了作为queue<Shape*>但我不想处理指针 - 意思是 *。

编辑,此代码编译。谢谢大家。 This article Guillaume Racicot 建议有助于更清楚地了解情况。

#include <queue>
#include <memory>

class Shape {
public:
    virtual int getPerimeter() =0;
};

typedef std::unique_ptr<Shape> base_ptr;

class Circle : public Shape {
public:
    Circle() {};
    virtual int getPerimeter() { return 1; };
};

class Square : public Shape {
public:
    virtual int getPerimeter() { return 0; };
};

class ShapeManager {
public:
    ShapeManager();
    void useShape() {
        if(shapes.empty())
            throw "Work stack is empty.";

        base_ptr s = std::move(shapes.front());
        s->getPerimeter();
        shapes.pop();
    }

    void submitShape(base_ptr b) {
        shapes.push(std::move(b));
    }
private:
    std::queue<base_ptr> shapes;
};

int main(int argc, char **argv) {
    ShapeManager s;
    base_ptr c = std::make_unique<Circle>();
    s.submitShape(std::move(c));
    s.useShape();
    return 1;
}

最佳答案

容器会让人分心。问题是 unique_ptr 是不可复制的;如果是,它就不是唯一的。所以您可能需要添加对 std::move 的调用:

base_ptr s = std::move(shapes.front());

这意味着与原始代码可能打算做的事情不同;它从容器中移除对象。如果这不是您想要的,那么 std::move 就不是正确的答案,并且 unique_ptr 可能不是正确的机制。

关于c++ - 管理标准容器中的抽象类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44949317/

相关文章:

c++ - 提取的接口(interface)命名约定

c++ - 模板函数与具有自动参数的命名 lambda

c++ - 调用 fork 后 gRPC 服务器中的 SSL 握手失败

c++ - 使用 libssh 链接期间 undefined symbol

c++ - 假装 packaged_task 是可复制构造的

c++ - 为什么 std::async 复制它的 const & 参数?

c++ - 为什么 gcc 仅针对统一初始化警告缩小转换?

c++ - 字符串文字的模板参数推导

c++ - 如何初始化由 unique_ptr 管理的数组的元素?

c++ - std::shared_ptr 和继承