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