我们可以声明一个抽象方法来返回抽象超类中的子类对象而不需要新的实例化吗?
Posted
技术标签:
【中文标题】我们可以声明一个抽象方法来返回抽象超类中的子类对象而不需要新的实例化吗?【英文标题】:Can we declare a abstract method to return subclass objects in abstract superclass without new instantiation? 【发布时间】:2019-11-03 14:04:06 【问题描述】:我想构建一个类(例如 VectorSpace),该类将抽象地存在某些方法。 我最近从 Java 迁移到 C++,我在尝试改写 Java 中的通用抽象方法声明时遇到了问题
情况是c++不允许声明如: 抽象类方法名(...) = 0; 另一方面,Java 允许返回类型是抽象类。 这在 c++ 中是不允许的,编译会导致错误说抽象类不能作为方法的返回类型。 我浏览了这个页面:returning an abstract class from a function。 所以我在 C++ 中做了以下操作:
//Fields are any classes which +,* defined on them
template<class F> class VectorSpace
virtual VectorSpace<F>* operator+(const VectorSpace<F>& el) const =0;
virtual VectorSpace<F>* operator-() const =0;
virtual VectorSpace<F>* operator*(const F& el) const =0;
....
;
class Vector : public VectorSpace<double>
....
Vector* operator+(const VectorSpace<double>& el) const return new Vector(....);
但是,这样做的问题是,每当应用任何运算符(例如 +、-)时,我都将使用“new”为作为 VectorSpace 子类的任何类(如 Vector)实例化一个对象,这必须手动删除。
有没有办法解决这个问题?
【问题讨论】:
你可以返回一个引用,但是VectorSpace<F>
必须在某个地方;如果您返回对临时对象的引用(并且您使用 operator +
表明您将返回临时对象),您将遇到其他问题。
为什么叫它VectorSpace?它的字面意思是从 VectorSpace你可以有另一个类,比如VectorWrapper
,它包装了一个指向抽象类的指针,例如通过std::unique_ptr<VectorSpace<double> >
。在此类中,您可以重载operator+
以将调用重定向到实现,然后返回一个新的本地构造的包装器。 std::unique_ptr
设施避免了手动删除,并且您拥有按值返回的重载运算符 - 因此它们易于使用。请注意,运算符 new
和 delete
仍然在后台调用并由 VectorWrapper 封装。
class VectorWrapper
VectorWrapper(std::unique_ptr<VectorSpace<double> > ptr)
: m_impl(std::move(ptr))
VectorWrapper operator+(const VectorWrapper& other)
return VectorWrapper(*m_impl + *other.m_impl);
private:
std::unique_ptr<VectorSpace<double> > m_impl;
;
它与类型擦除 C++ 习语密切相关。
编辑:你还需要实现复制构造函数和赋值来调用std::make_unique
等。或者如果向量是不可变的——就像数学对象一样——你可以考虑使用std::shared_ptr
,但它可能会更慢取决于在您的代码中复制 VectorWrapper
的频率。
【讨论】:
以上是关于我们可以声明一个抽象方法来返回抽象超类中的子类对象而不需要新的实例化吗?的主要内容,如果未能解决你的问题,请参考以下文章