C++ 抽象类与多态性

C++ 抽象类与多态性,c++,polymorphism,clone,virtual,C++,Polymorphism,Clone,Virtual,我正在用抽象类做一些事情 #include <iostream> #include <vector> using namespace std; class Shape { protected: int m_size; public: int getSize() { return m_size; } virtual bool isEqual(Shape *rhs) = 0; }; 我想这样使用它: C.add(Circle(10)); 解决

我正在用抽象类做一些事情

#include <iostream>
#include <vector>

using namespace std;

class Shape
{
protected:
    int m_size;
public:
    int getSize() { return m_size; }

    virtual bool isEqual(Shape *rhs) = 0;
};
我想这样使用它:

C.add(Circle(10));

解决方案是什么?

不要按值存储多态对象。这可能导致严重后果

在您的例子中,甚至不可能按值存储Shape类型的对象,因为该类具有纯虚拟方法

如果您想要更好的资源管理,例如自动调用delete,您可以使用shared_ptr或unique_ptr


.

不按值存储多态对象。这可能导致严重后果

在您的例子中,甚至不可能按值存储Shape类型的对象,因为该类具有纯虚拟方法

如果您想要更好的资源管理,例如自动调用delete,您可以使用shared_ptr或unique_ptr


.

如果要统一使用容器并保存任何类型的形状圆、矩形,则不能。。在同一个容器中。例如,当前可以使用基类指针添加任何形状。但如果要添加对象而不是指针,则必须为每种类型声明一个容器。您将无法统一处理对象。

如果要统一使用容器并保存任何类型的形状圆、矩形,则无法。。在同一个容器中。例如,当前可以使用基类指针添加任何形状。但如果要添加对象而不是指针,则必须为每种类型声明一个容器。您将无法统一处理对象。

您需要将新对象的创建移动到容器::add,以便仅当对象不在容器中时才创建该对象。实现此功能的一种方法是在形状中声明纯虚拟克隆函数,然后在圆圈中定义它:

然后,您可以按要添加的值传递对象,它将调用Clone:


您需要将新对象的创建移动到Container::add,以便仅当对象不在容器中时才创建该对象。实现此功能的一种方法是在形状中声明纯虚拟克隆函数,然后在圆圈中定义它:

然后,您可以按要添加的值传递对象,它将调用Clone:


与克隆方法类似, 您可以通过类似于C++11的方式修改方法add:

template<typename T, typename...Ts>
bool Container::add(Ts&&... args)
{
    std::unique_ptr<T> newShape(new T(std::forward<Ts>(args)...));
    for (const Shape* shape : v) {
        const auto* shapeT = dynamyc_cast<const T*>(shape);

        if (shapeT != nullptr && shapeT->isEqual(newShape) ) {
            return false;
        }

    }
    v.push_back(newShape.release()); // better to have std::vector<std::unique_ptr<Shape>>...
    return true;
}
然后像这样使用它:

c.add<Circle>(10);

与克隆方法类似, 您可以通过类似于C++11的方式修改方法add:

template<typename T, typename...Ts>
bool Container::add(Ts&&... args)
{
    std::unique_ptr<T> newShape(new T(std::forward<Ts>(args)...));
    for (const Shape* shape : v) {
        const auto* shapeT = dynamyc_cast<const T*>(shape);

        if (shapeT != nullptr && shapeT->isEqual(newShape) ) {
            return false;
        }

    }
    v.push_back(newShape.release()); // better to have std::vector<std::unique_ptr<Shape>>...
    return true;
}
然后像这样使用它:

c.add<Circle>(10);

但问题不建议按值存储,只传递给按值添加。但问题不建议按值存储,只传递给按值添加。这仍将调用new,涉及对复制构造函数的额外调用,并且每个派生类都需要一个方法克隆。好处是什么?好处是它解决了拥有指向多态对象的指针容器的问题,并且仅当对象不在容器中时才添加对象。你对如何解决这个问题还有其他想法吗?请注意,我的解决方案可以很容易地扩展为使用智能指针,并避免在容器析构函数中手动删除。这仍然会调用new,包括对复制构造函数的额外调用,并且每个派生类都需要一个方法克隆。好处是什么?好处是它解决了拥有指向多态对象的指针容器的问题,并且仅当对象不在容器中时才添加对象。你对如何解决这个问题还有其他想法吗?请注意,我的解决方案可以很容易地扩展到使用智能指针,并避免在容器析构函数中手动删除。顺便说一句,虚拟析构函数丢失。是否需要虚拟析构函数?@bandara:添加它几乎是免费的,而且一旦在子类中有析构函数,它就可以避免memleak…顺便说一句,虚拟析构函数丢失。是否需要虚拟析构函数?@bandara:几乎可以自由添加它,并且一旦在子类中有析构函数,它就可以避免memleak。。。
v.push_back(shape.Clone());
template<typename T, typename...Ts>
bool Container::add(Ts&&... args)
{
    std::unique_ptr<T> newShape(new T(std::forward<Ts>(args)...));
    for (const Shape* shape : v) {
        const auto* shapeT = dynamyc_cast<const T*>(shape);

        if (shapeT != nullptr && shapeT->isEqual(newShape) ) {
            return false;
        }

    }
    v.push_back(newShape.release()); // better to have std::vector<std::unique_ptr<Shape>>...
    return true;
}
c.add<Circle>(10);