我有一个抽象类Number
,它带有4个纯虚拟运算符(+
,-
,/
,*
)。我想制作两个派生类Integer
和Real
并在那里覆盖这些运算符。我不太了解如何声明运算符。我没有在网上找到与我的情况类似的示例。
我的问题是:
在抽象基类Number
中,我的运算符必须返回引用Number&
或指针Number*
,因为我不能返回抽象类本身。但是我应该以什么作为论点呢? Number&
或Number*
也一样,但是我需要在班级中存储数字,我的基类中是否应该有类似void* num
的东西?
想象一下,我有
class Number {
...
virtual Number& operator+(const Number&) = 0;
};
如何在派生类Integer
中覆盖此运算符?
答案 0 :(得分:4)
我知道,但是我的导师坚持要像在抽象类中进行练习一样,将其作为覆盖纯虚拟操作符来执行,但是我真的不明白。
好吧,您可以从中了解两件事:
问题在于类Integer
和Real
最有可能具有不同的内部表示形式-因此您将无法在不了解具体类型的情况下进行加法/乘法/...。您收到作为第二个操作数。此外,还不清楚混合操作数类型的返回类型应该是什么。
我真的不需要atm仅添加real + int real + real,int + int
好吧,我们可以抓住这一点:
class Number
{
public:
virtual ~Number() { } // in any case, a virtual base class should have a virtual destructor!
// fine so far:
virtual Number& operator+(Number const&) const = 0;
// we are not going to change the ^
// own instance, so we'd rather have this operator const
// (in contrast to operator+=)
};
class Integer : public Number
{
public:
Integer& operator+(Number const& other) const override
// ^ co-variant return type, so that's fine
{
// at very first, we make sure that we actually received
// an instance of type Integer
auto o = dynamic_cast<Integer const*>(&other);
if(!o)
// if not, throwing an exception is a good candidate
// for error handling...
throw std::invalid_argument("argument must be of type Integer");
// now as we know it IS an Integer:
return Integer(this->value + o->value); // or whatever...
// OOPS - the returned object gets lost when the function is left...
}
};
如果您也想添加Real
,则将进行另一种类型转换。假设Integer + Real
产生Real
,那么您就不得不将返回类型改回Number
。
但是,仍然存在一个很大的问题:函数离开后,返回的对象将被销毁,因此返回的引用是悬空的。
我们必须通过某种方式解决此问题。不过,引用并不适合,因此我们可能会选择智能指针:
class Number
{
virtual std::unique_ptr<Number> operator+(Number const&) const = 0;
};
class Integer : public Number
{
std::unique_ptr<Number> operator+(Number const& other) const override
// ^
// unfortunately, now, as ordinary struct, no co-variance possible any more
{
return std::make_unique<Integer>(this->value + o->value);
}
};
这个问题再次说明了实际选择的方法是多么不恰当...