C++:如何在抽象类的方法中返回抽象类

3

我有一个抽象类,它有两个派生类。我试图在基类中重载operator+,这样我就可以像这样进行操作:derivedClass=derivedClass+differentDerivedClass:

class iMatrix{
iMatrix operator+(const iMatrix& obj)
}

class UsualMatrix : public iMatrix

class SparseMatrix : public iMatrix 

在main函数内部,我想要进行以下操作:
SparseMatrix a, b;
UsualMatrix c=a+b;

我有拷贝构造函数和其他可能有用的东西。现在,如果我像这样创建函数:
iMatrix operator+(const iMatrix& obj)

编译器(Xcode中的LLVM)显示“返回类型'iMatrix'是抽象类”,但理论上其他所有内容都应该正常工作。我已经阅读了手册和其他StackOverflow线程,所以我尝试了这个:

iMatrix& operator+(const iMatrix& obj)

而一个函数本身会“将obj添加到this”并返回*this。问题在于当我执行c=a+b时,a变成了等于c,但它本不应该改变。

a=
1 1 
1 1 
b=
1 1 
1 1 
a+b=c; 
c=
2 2 
2 2 
b=
1 1 
1 1 
a=
2 2 
2 2 

我该怎么办?加法和乘法必须在基类中实现,但我不知道如何修复此错误。 非常感谢您的任何建议。


2
多态和值语义不适合在一起使用。 - Guillaume Racicot
你真的需要一个抽象类型来表示矩阵吗? - juanchopanza
@juanchopanza 是的,因为这是大学任务,教我们抽象类和其他东西 :) - JonathanX64
好的,也许这应该是一个反例。你已经发现了这种方法的一个问题。 - juanchopanza
2个回答

2
你的意图设计中存在的问题是抽象返回类型。抽象类不能按值返回,只有具体类能按值返回。因此,要返回抽象类,您需要一个指针或引用。
不幸的是,这与 operator+() 的语义不兼容:
要么您通过引用返回当前对象,并在操作中更改它;但这与预期的语义不符,而且还可能导致错误答案(例如,在执行 c = a+b+a+b; 时);
要么您将返回对临时对象的引用。但这会导致未定义行为,因为当函数返回时,临时对象就会消失,使得引用无关了。
最后,operator+() 将没有办法自己决定用于返回的具体类型。例如:SparseMatrix a; UsualMatrix b; a+b; 对于矩阵a+b应该使用哪种类型?
您可以在操作符中使用多态和抽象类型,但不能作为返回类型。要实现这种东西,您需要选择自己的一组操作符,并让调用者手动管理临时结果。
UsualMatrix c,tmp; 
SparseMatrix a,b,x; 
...
a.add(b, tmp);
tmp.add(x, c);   // c = a+b+x; 

使用 virtual void add(const iMatrix& x, iMatrix z) = 0; 实现


0
一个解决方案可能是像这样的非成员函数:

template <
  typename T,
  typename = typename std::enable_if<std::is_base_of<iMatrix, T>::value>::type
>
T operator+(T const & a, T const & b) {
   T res; 
   // calculate res
   return res;
}

iMatrix 是一个抽象类,因此您无法返回它的实例。在上面的示例中,我们对 iMatrix 的所有派生类 T 重载了 operator+,并可以返回 T 实例。


对我来说,这似乎是个好的解决方案,但是却产生了相同的错误:“重载的'operator+'必须是一元或二元运算符(有3个参数)”。 - JonathanX64
不要将其编写为成员函数 :-) @JonathanX64 - amin
这不会破坏运行时多态性吗? - juanchopanza
@juanchopanza 当UT都是派生类时,operator+(T const&,U const&)应该发生什么? - amin
@amin 确切地说,应该发生什么? - juanchopanza
显示剩余10条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接